我想在我的项目中使用Tabulator,该项目尚未与Svelte集成。这是我之前已经使用过的非常完整的数据表库。但是,当我尝试使用操作按钮(编辑,删除...)创建典型列时,我总是使用它们的Custom Formatters来将html作为字符串返回。
格式化列的函数返回以下内容:
return '<ul class="actions_row"><li><custom-button on:click={handleClick}>Edit</custom-button></li></ul>';
<custom-button />
是使用<svelte:options>
创建的自定义元素,并通过 index.html (<script src="lib/CustomButton.js"></script>
)添加到项目中。
自定义按钮显示在表格中,但它无法转发事件。似乎该组件无法在其自身范围之外进行通信。
答案 0 :(得分:1)
您的自定义格式化程序返回的字符串将作为“普通” HTML处理,因此Svelte语法不再可用...即on:click
是Svelte语法,浏览器将不处理。
我不是自定义元素专家,但是很不幸,according to others,您要尝试做的事情是不可能的。也就是说,您不能仅通过HTML在自定义元素上注册自定义事件侦听器。您必须必须使用JS来完成。像这样:
<script>
document.querySelector('custom-button')
.addEventListener('my-event', e => {
console.log(e.detail)
})
</script>
此外,请注意,Svelte中来自自定义元素的事件当前受到某些限制(请参见this issue)。
因此,为了使自定义元素具有自定义事件,您必须使用某种解决方法。例如,以下是触发上述片段中的侦听器的组件:
<svelte:options tag="custom-button" />
<script>
import { onMount } from 'svelte';
let el
onMount(() => {
const interval = setInterval(() => {
let event = new CustomEvent('my-event', {
detail: {time: Date.now()},
bubbles: true,
composed: true, // needed for the event to traverse beyond shadow dom
})
el.dispatchEvent(event)
}, 1000)
return () => {
clearInterval(interval)
}
})
</script>
<button bind:this={el}><slot /></button>
请注意,此类代码对旧版浏览器的支持有限。
说了这么多,对于您的示例而言,正是这样,您显然可以通过在本机浏览器onclick
而非Svelte的on:click
中注册事件来使其工作。我仍然不是CE专家,但我的猜测是浏览器会处理所有本机元素(例如,单击或按下CE元素)上都可用的标准事件...
因此,这似乎应该对您有用:
return '<ul class="actions_row"><li><custom-button onclick="handleClick">Edit</custom-button></li></ul>';
注意:onclick="handleClick"
,而不是on:click={handleClick}
。您现在处在标准浏览器领域,因此适用通常的规则,就像使用普通的<button>
... handleClick
一样,必须在范围内可用,等等。
答案 1 :(得分:0)
发生这种情况的原因是因为您正在从格式化程序中返回HTML字符串,这意味着在将其转换为字符串的过程中,所有的JS绑定(例如click事件处理程序)都将被删除。 (单击功能绑定的上下文将丢失,因为该功能仅在写入字符串而不是在解析位置写入的函数中才有效) >
为了保留绑定,您应该返回表示按钮的 Node Object 本身,而不仅仅是按钮的HTML,这样,其他事件添加到该按钮的事件绑定库将保持不变。
答案 2 :(得分:0)
我正在使用自定义组件中的以下代码调度事件。
<script>
import { get_current_component } from "svelte/internal";
const thisComponent = get_current_component();
// Standard function for dispatching custom events
const dispatchWcEvent = (name, detail) => {
thisComponent.dispatchEvent(new CustomEvent(name, {
detail,
composed: true, // propagate across the shadow DOM
}));
};
function handleClose(event) {
event.preventDefault();
// dispatching collpase event
dispatchWcEvent("collapse", "tooltip")
}
<script>
<svelte:options tag="my-component"></svelte:options>
<span class="icon-cross" on:click={event => handleClose(event)}>X</span>
在 Real DOM 中捕获自定义事件(js 文件不是 svelte 项目的一部分)
let shadow = document.querySelectorAll("my-component");
// if you have single occurence then you can skip the foreach loop and use querySelector
shadow.forEach(function(elem) {
elem.addEventListener("collapse", e => {
alert('event handled');
});
});