将事件指令添加到 svelte html 表达式?
Add event directive to svelte html expression?
我想在 svelte 中通过 html 表达式添加自定义按钮。
通过文档 here,我可以使用 @html 标签来做到这一点。
{@html
`
<button>
click me
</button>
`
}
我现在想向 html 字符串添加一个指令事件处理程序,即单击按钮时将调用的本地定义函数。到目前为止我尝试了什么:
{@html
`
<button
on:click="${()=>doSomething()}">
click me
</button>
`
}
然而,如我所料,它没有用。我在想可能还有另一种方法,但到目前为止还想不出一个
从概念上讲,使用 @html
指令等同于执行 el.innerHTML = myHtmlString
.
换句话说,在您的 HTML 字符串的上下文中,您完全不在 Svelte 的领域(并且完全在本机浏览器的领域)。
on:click
是特殊的 Svelte 语法,浏览器不会处理它。所以如果你想要你的 HTML 字符串中的事件,你需要返回原始 HTML/JS。也就是说,改用 onclick
。
当然,onclick
和on:click
的语义完全不同。对于 onclick
,你只能传递一个字符串,当事件发生时,它将是 eval
'(而对于 on:click
,你传递一个函数 reference, 当事件发生时将被调用)。
为了更清楚地说明这一点,让我们回顾一下 Svelte 的语法:
<button on:click={doSomething}>Click me</button>
相比之下,在原始 HTML 中,它看起来像:
{@html '<button onclick="doSomething()">Click click!</button>'}
查看重要区别:使用 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>'}
这太丑了...您可以改为这样做,以避免污染全局范围:
<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>'}
现在我们正在污染 DOM ids...我们可以通过用 Svelte 控制的元素包装来进一步避免这种情况,我们可以使用 bind:this={el}
...
总而言之,最好避免 @html
字符串中的动态元素,因为您会在其中失去 Svelte 的所有优势。 @html
最适合呈现静态 HTML 内容。
为什么要将按钮放在字符串中,而不是让 Svelte 管理它?
如果你真的需要走这条路,你可能也会对 this dirty trick 感兴趣,我绝对不建议使用它(我永远不会在我自己的代码中使用它)...但是这可能会让您对您要实现的目标有更深入的了解。
我想在 svelte 中通过 html 表达式添加自定义按钮。 通过文档 here,我可以使用 @html 标签来做到这一点。
{@html
`
<button>
click me
</button>
`
}
我现在想向 html 字符串添加一个指令事件处理程序,即单击按钮时将调用的本地定义函数。到目前为止我尝试了什么:
{@html
`
<button
on:click="${()=>doSomething()}">
click me
</button>
`
}
然而,如我所料,它没有用。我在想可能还有另一种方法,但到目前为止还想不出一个
从概念上讲,使用 @html
指令等同于执行 el.innerHTML = myHtmlString
.
换句话说,在您的 HTML 字符串的上下文中,您完全不在 Svelte 的领域(并且完全在本机浏览器的领域)。
on:click
是特殊的 Svelte 语法,浏览器不会处理它。所以如果你想要你的 HTML 字符串中的事件,你需要返回原始 HTML/JS。也就是说,改用 onclick
。
当然,onclick
和on:click
的语义完全不同。对于 onclick
,你只能传递一个字符串,当事件发生时,它将是 eval
'(而对于 on:click
,你传递一个函数 reference, 当事件发生时将被调用)。
为了更清楚地说明这一点,让我们回顾一下 Svelte 的语法:
<button on:click={doSomething}>Click me</button>
相比之下,在原始 HTML 中,它看起来像:
{@html '<button onclick="doSomething()">Click click!</button>'}
查看重要区别:使用 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>'}
这太丑了...您可以改为这样做,以避免污染全局范围:
<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>'}
现在我们正在污染 DOM ids...我们可以通过用 Svelte 控制的元素包装来进一步避免这种情况,我们可以使用 bind:this={el}
...
总而言之,最好避免 @html
字符串中的动态元素,因为您会在其中失去 Svelte 的所有优势。 @html
最适合呈现静态 HTML 内容。
为什么要将按钮放在字符串中,而不是让 Svelte 管理它?
如果你真的需要走这条路,你可能也会对 this dirty trick 感兴趣,我绝对不建议使用它(我永远不会在我自己的代码中使用它)...但是这可能会让您对您要实现的目标有更深入的了解。