将事件指令添加到 svelte html 表达式?

ndr*_*_rr 1 html javascript svelte

我想通过 svelte 中的 html 表达式添加自定义按钮。通过这里的文档,我可以使用@html标签来做到这一点

{@html 
`
 <button>
   click me
 </button>
`
}
Run Code Online (Sandbox Code Playgroud)

我现在想向 html 字符串添加一个指令事件处理程序,即单击按钮时将调用的本地定义函数。到目前为止我尝试过的:

{@html 
`
 <button
   on:click="${()=>doSomething()}">
   click me
 </button>
`
}
Run Code Online (Sandbox Code Playgroud)

然而,正如我所料,它没有奏效。我在想可能有另一种方法,但到目前为止还没有想出一个

rix*_*ixo 5

从概念上讲,使用该@html指令等同于执行el.innerHTML = myHtmlString.

换句话说,在您的 HTML 字符串的上下文中,您完全脱离了 Svelte 的领域(并且完全处于本机浏览器的领域)。

on:click是特殊的 Svelte 语法,浏览器不会处理它。因此,如果您希望在 HTML 字符串中包含事件,则需要返回原始 HTML/JS。也就是onclick改用。

当然, 的语义与 的语义onclick完全不同on:click。对于onclick,您只能传递一个字符串,该字符串将eval在事件发生时被调用(而对于on:click,您传递的是一个函数引用,它将在事件发生时被调用)。

为清楚起见,让我们回忆一下 Svelte 的语法:

<button on:click={doSomething}>Click me</button>
Run Code Online (Sandbox Code Playgroud)

相比之下,在原始 HTML 中,这看起来像:

{@html '<button onclick="doSomething()">Click click!</button>'}
Run Code Online (Sandbox Code Playgroud)

查看重要区别:使用onclick,您需要调用doSomething()函数,否则单击时不会发生任何事情。

现在,额外的乐趣:这个doSomething函数需要在范围内可用......也就是说,你必须将它附加到window

<script context="module">
  // note: using context=module to avoid adding this function to window
  //       multiple times
  window.doSomething = () => { ... }
</script>
{@html '<button onclick="doSomething()">Click click!</button>'}
Run Code Online (Sandbox Code Playgroud)

这很难看......你可以做这样的事情,以避免污染全局范围:

<script>
  import { onMount } from 'svelte'

    const doSomething = () => { ... }

    onMount(() => {
        const btn = document.querySelector('#grab-me')
        btn.addEventListener('click', doSomething)
    })
</script>

{@html '<button id="grab-me">Click click!</button>'}
Run Code Online (Sandbox Code Playgroud)

现在我们正在污染 DOM id……我们可以通过用 Svelte 控制的元素包装来进一步避免这种情况,我们可以用bind:this={el}……获取引用。

总而言之,@html最好避免使用字符串中的动态元素,因为您会在其中失去 Svelte 的所有好处。@html最适合呈现静态 HTML 内容。

为什么要将按钮放在字符串中,而不是让 Svelte 管理它?

如果你真的需要走这条路,你可能也对这个肮脏的技巧感兴趣,我绝对不推荐使用它(我永远不会在我自己的代码中使用它)......但这可能会让你更深入地了解你想要达到的目标。