如何将参数传递给 on:click in Svelte?

Fel*_*Dev 54 svelte svelte-3

将函数绑定到按钮非常简单直接:

<button on:click={handleClick}>
    Clicks are handled by the handleClick function!
</button>
Run Code Online (Sandbox Code Playgroud)

但是当我这样做时,我没有看到将参数(参数)传递给函数的方法:

<button on:click={handleClick("parameter1")}>
    Oh no!
</button>
Run Code Online (Sandbox Code Playgroud)

该函数在页面加载时被调用,并且永远不会再次调用。

是否有可能将参数传递给从 调用的函数on:click{}


**编辑:**

我刚刚找到了一个hacky的方法来做到这一点。从内联处理程序调用该函数有效。

<button on:click={() => handleClick("parameter1")}>
    It works...
</button>
Run Code Online (Sandbox Code Playgroud)

V. *_*bor 36

TL; 博士

只需将处理程序函数包装在另一个函数中。为了优雅,请使用箭头功能。


您必须使用函数声明,然后使用参数调用处理程序。箭头函数非常适合这种情况。

为什么我需要另一个函数包装器?

如果您只使用处理程序并传递参数,它会是什么样子?

大概是这样的:

<button on:click={handleClick("arg1")}>My awesome button</button>
Run Code Online (Sandbox Code Playgroud)

但是请记住,handleClick("arg1")这就是您立即调用该函数的方式,这正是您以这种方式调用该函数时发生的情况,当执行到达此行时将调用它,而不是像预期的那样,ON BUTTON CLICK ...

因此,您需要一个函数声明,该声明将仅由单击事件调用,并在其中使用任意数量的参数调用处理程序。

<button on:click={() => handleClick("arg1", "arg2")}>
    My awesome button
</button>
Run Code Online (Sandbox Code Playgroud)

正如@Rich Harris(Svelte 的作者)在上面的评论中指出的那样:这不是黑客攻击,而是文档在他们的教程中也显示的内容:https : //svelte.dev/tutorial/inline-handlers

  • 在哲学层面上,我想这种方式也使它尽可能接近普通的 JavaScript。“当有疑问时,像 JavaScript 一样执行”的想法在这里成立(当然,他们在幕后做了一些工作以提高效率)。事实上,如果我不费心去查找它,我可能会直觉地选择这个解决方案:P (3认同)
  • `on:click={() =&gt; handleClick("arg1", "arg2")}` 是正确的方法 (2认同)

小智 21

Rich 在评论中回答了这个问题,所以要归功于他,但是在点击处理程序中绑定参数的方法如下:

<a href="#" on:click|preventDefault={() => onDelete(projectId)}>delete</a>
<script>
function onDelete (id) {
  ...
}
</script>
Run Code Online (Sandbox Code Playgroud)

为了为也有此问题的人提供一些额外的细节,如果不是,则应该在文档中,您还可以在这样的处理程序中获取 click 事件:

<a href="#" on:click={event => onDelete(event)}>delete</a>
<script>
function onDelete (event) {
  // if it's a custom event you can get the properties passed to it:
  const customEventData = event.detail

  // if you want the element, you guessed it:
  const targetElement = event.target
  ...
}
</script>
Run Code Online (Sandbox Code Playgroud)

Svelte 文档/教程:内联处理程序


Ste*_*aes 6

文档中没有提到任何明确的方法,您的解决方案可以工作,但它确实不是很优雅。我自己的首选解决方案是在脚本块本身中使用柯里化

const handleClick = (parameter) => () => {
   // Actual function
}
Run Code Online (Sandbox Code Playgroud)

在 HTML 中:

<button on:click={handleClick('parameter1')>
   It works...
</button>
Run Code Online (Sandbox Code Playgroud)

谨防柯里化

正如评论中提到的,柯里化有其缺陷。在上面的示例中,最常见的一个handleClick('parameter1')不会在单击时触发,而是在渲染时触发,返回一个函数,该函数又将在单击时触发。这意味着该函数将始终使用“parameter1”作为其参数。

因此,只有当使用的参数是某种常量并且一旦渲染后就不会改变时,使用此方法才是安全的。

这会让我想到另一点:

  1. 如果它是使用参数的常量,您也可以使用单独的函数

    const handleParameter1Click = () => handleClick('parameter1');
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果该值是动态的但在组件内可用,则仍然可以使用独立函数来处理:

    let parameter1;
    const handleParameter1Click = () => handleClick(parameter1);
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果该值是动态的,但无法从组件中获得,因为这取决于某种范围(例如,#each 块中呈现的项目列表),那么“hacky”方法会效果更好。然而,我认为在这种情况下最好将列表元素本身作为一个组件并回退到情况 #2

总而言之:柯里化在某些情况下会起作用,但不建议这样做,除非您非常了解并小心如何使用它。

  • 不要这样做!只需创建一个内联函数(`on:click={() =&gt; handleClick('parameter1')}`) (5认同)
  • 刚刚意识到这就是您正在回应的提案。我建议反对柯里化方法的原因有两个——首先,不太清楚发生了什么(人们倾向于认为“handleClick('parameter1')”是*当点击发生时*发生的事情,这是错误的。其次,这意味着每当参数发生变化时,处理程序都需要反弹,这是次优的。目前,存在一个错误,这意味着无论如何都不起作用 https://svelte.dev/repl/a6c78d8de3e2461c9a44cf15b37b4dda?version=3.12.1 (2认同)