将值传递给函数时,Svelte 值不会在屏幕上更新

Svelte value not updating on screen when passing a value to a function

有点困惑为什么下面的方法不起作用。我已经尝试过这个,我没有将参数传递给函数并且可以让 UI 更新但是如果我传递参数并对它做同样的事情它会在代码中更新它并且我可以console.log 出来了,但是 UI 没有更新。

这个作品:

<script>
   import { text, toggle_class } from "svelte/internal";

   let line1 = {name:"line 1", display:"some text here", originalText:"some init text", visible:true};

function toggleView(){ 
    line1.visible = !line1.visible;
    if(!line1.visible) line1.display = "*************"
    else line1.display = line1.originalText
};
</script>

<main>
    <button on:click="{toggleView}">{line1.display}</button>
</main>

这不起作用:

<script>
   import { text, toggle_class } from "svelte/internal";

   let line1 = {name:"line 1", display:"some text here", originalText:"some init text", visible:true};

function toggleView(field){ 
    field.visible = !field.visible;
    if(!field.visible) field.display = "*************"
    else field.display = field.originalText
};
</script>

<main>
    <button on:click="{toggleView(line1)}">{line1.display}</button>
</main>

我认为这可能是因为从 Svelte 的角度来看,我将它分配给了一个局部变量,但我不确定我还能如何调用一个函数来使它可重用,因为我这样做是为了一堆线。

如有任何帮助,我们将不胜感激。


更新 - 已解决

以下作品基于 Thomas 的以下回答:

<script>
    import { text, toggle_class } from "svelte/internal";
    var lines = {
        line1: {
            name: "line 1",
            display:"some text here",
            originalText:"some init text",
            visible:true
        }
    };
    
    function toggleView(field) {
        return function() {
            lines[field].visible = !lines[field].visible;
            if (!lines[field].visible) {
                lines[field].display = "*************";
            } else {
                lines[field].display = lines[field].originalText;
            }
        }
    }
</script>

<main>
    <button on:click="{toggleView('line1')}">{lines.line1.display}</button>
</main>

在原始HTML + JS中,像onclick这样的内联事件处理程序实际上是一些代码,当事件发生时将被执行。特别是,如果您在处理程序中使用函数,则必须调用它:

示例(不是 Svelte):

<button onclick="toggleView()" />

相比之下,在 Svelte 中,事件处理程序应该是一个函数,它将在事件发生时被调用。

好的,因为 toggleView 是一个函数:

<button on:click={toggleView} />

不正常,因为每次渲染标记时它都会调用 toggleView()(即当反应变量发生变化时),并且 togggleView() 的 return 值绑定到 click 事件:

<button on:click={toggleView()} />

如果您需要将本地参数传递给事件处理程序,那么您需要 包装 函数以仍然得到您想要的(当事件发生时调用整个函数) ,而不是在标记重新生成时):

示例,OK + 参数:

<button on:click={() => toggleView(line1)} />

请注意,这里的处理程序是 () => toggleView(line1),而不是 toggleView(line1)

当您将 on:click 设置为 toggleView(line1) 时,该函数会立即执行,就像您将其设置为 toggleView() 而不是 toggleView其他,工作示例。

您有两种方法可以解决此问题。最常见的方法是将 on:click 处理程序变成 lambda/anonymous 函数:

<button on:click="{() => toggleView(line1)}">{line1.display}</button>

另一种不太常见的方法是修改您的处理程序函数并将其转换为柯里化函数:

function toggleView(field) {
    return function() { 
        field.visible = !field.visible;
        if(!field.visible) field.display = "*************"
        else field.display = field.originalText
    };
};

在这种情况下 on:click={toggleView(field)} 将 return 绑定到单击处理程序的函数,并且该函数将在单击按钮时实际执行。