66

Binding a function to a button is easy and straightforward:

<button on:click={handleClick}>
    Clicks are handled by the handleClick function!
</button>

But I don't see a way to pass parameters (arguments) to the function, when I do this:

<button on:click={handleClick("parameter1")}>
    Oh no!
</button>

The function is called on page load, and never again.

Is it possible at all to pass parameters to function called from on:click{}?


**EDIT:**

I just found a hacky way to do it. Calling the function from an inline handler works.

<button on:click={() => handleClick("parameter1")}>
    It works...
</button>
4

8 回答 8

53

TL;博士

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


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

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

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

大概是这样的:

<button on:click={handleClick("arg1")}>My awesome button</button>

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

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

<button on:click={() => handleClick("arg1", "arg2")}>
    My awesome button
</button>

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

于 2020-04-04T08:02:15.667 回答
24

Rich 在评论中回答了这个问题,因此感谢他,但在点击处理程序中绑定参数的方法如下:

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

为了为同样为此苦苦挣扎的人提供一些额外的细节,如果不是,它应该在文档中,您还可以在这样的处理程序中获取 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>

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

于 2019-11-02T18:17:29.727 回答
2

我得到了它的工作:

<a href="#" on:click|preventDefault={onDelete.bind(this, project_id)}>delete</a>

function onDelete(id) {
}
于 2019-11-01T17:26:05.090 回答
1

哈巴狗解决方案

用 分配!=。是的,分配 !=. 诡异如地狱。例子Foo(on:click!='{() => click(i)}')。这是每个 svelte-preprocess 的文档(在 pug 中包含模板的必要转译器)

Pug 将元素属性内的所有内容编码为 html 实体,因此attr="{foo && bar}"变为attr="foo &amp;&amp; bar". 为了防止这种情况发生,不要使用不会对您的属性值进行编码的=运算符使用!=[...] 这也是传递回调所必需的。

就个人而言,我会为此使用一个 util 函数,因为 assign with!=太困扰我了。

// util fn
const will = (f, v) => () => f(v);
// in pug template we can again assign with =
Foo(on:click='{will(click, i)}')
于 2021-09-15T08:16:37.800 回答
1

这是一个 debounce 方法和事件参数:

<input type="text" on:keydown={event => onKeyDown(event)} />


const onKeyDown = debounce(handleInput, 250);

async function handleInput(event){
    console.log(event);
}
于 2019-12-06T22:08:00.103 回答
1

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

const handleClick = (parameter) => () => {
   // actual function
} 

在 HTML

<button on:click={handleClick('parameter1')>
   It works...
</button>

小心咖喱

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

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

这会让我想到另一点:

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

const handleParameter1Click = () => handleClick('parameter1');

2) 如果该值是动态的但在组件中可用,则仍然可以使用独立函数来处理:

let parameter1;
const handleParameter1Click = () => handleClick(parameter1);

3)如果该值是动态的,但组件不可用,因为这取决于某种范围(例如:在#each 块中呈现的项目列表),“hacky”方法会更好地工作。但是我认为在这种情况下最好将列表元素本身作为一个组件并回退到案例#2

总结:currying 在某些情况下会起作用,但除非您非常了解并小心使用它,否则不建议使用它。

于 2019-10-07T05:35:14.093 回答
0

我在用着:

{#each data as item}    
   <li on:click={handle(item)}>{item.name}</li>
{/each}

...并且它在渲染时没有运行该功能,它在点击时起作用。

于 2021-08-24T22:25:10.100 回答
0

有发布死亡的风险,请查看https://svelte.dev/repl/08aca4e5d75e4ba7b8b05680f3d3bf7a?version=3.23.1

可排序的表。注意以一种神奇的方式将参数传递给标题点击处理函数。不知道为什么会这样。自动咖喱可能吗?

于 2021-03-24T06:49:47.603 回答