【问题标题】:Svelte value not updating on screen when passing a value to a function将值传递给函数时,Svelte 值不会在屏幕上更新
【发布时间】:2021-02-19 14:14:33
【问题描述】:

对于以下为什么不起作用有点困惑。我已经尝试过这种方法,我不向函数传递参数并且可以更新 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>

【问题讨论】:

    标签: javascript svelte svelte-3


    【解决方案1】:

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

    您有两种方法可以解决此问题。最常见的方法是将您的 on:click 处理程序转换为 lambda/匿名函数:

    <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)} 将返回一个绑定到单击处理程序的函数,并且该函数将在单击按钮时实际执行。

    【讨论】:

    • 感谢您的回复。我尝试了这两个选项,但它仍然没有更新。在 Svelte REPL 中试试这个:
    • 您有两个不同的问题:首先,您需要选择一种方法或另一种方法,但您同时使用了这两种方法 - 它只是行不通。要么使用匿名处理程序方法,要么使用 curried 函数方法。
    • 您的第二个问题是期望更改原始对象副本上的对象属性以触发重新渲染(从而更新您的按钮文本)。为了让 Svelte 意识到需要重新渲染,原始对象需要通过位于赋值的左侧来显式更新。我在这里创建了一个可能的解决方法(还有其他方法)的 REPL:svelte.dev/repl/6356de92fe894ae385c33d80873351e3?version=3.29.4
    • 我尝试了每一个都做,但没有奏效,但是您的 REPL 将其转换为包含所有行的行对象就可以了。非常感谢您的帮助。
    • 不客气。这是另一种我认为更简洁的方法,使用数组来表示 lines 而不是对象:svelte.dev/repl/4a91c14ccb604e61a285a1dd1f849430?version=3.29.4 我还使用了其他处理程序方法来说明这一点。
    【解决方案2】:

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

    示例(不是 Svelte):

    <button onclick="toggleView()" />
    

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

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

    <button on:click={toggleView} />
    

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

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

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

    示例,OK + 参数:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 2021-10-03
      • 2012-05-07
      • 2023-01-16
      • 2019-12-11
      • 2013-06-25
      相关资源
      最近更新 更多