1

我想在我的项目中使用Tabulator ,它还没有与 Svelte 集成。是一个非常完整的数据表库,我之前已经用过。但是,当我尝试使用操作按钮(编辑、删除...)创建典型列时,我总是使用他们的自定义格式化程序,将 html 作为字符串返回。

格式化列的函数返回如下内容:

return '<ul class="actions_row"><li><custom-button on:click={handleClick}>Edit</custom-button></li></ul>';

<custom-button />是使用index.html ( )创建<svelte:options>并添加到项目中的自定义元素。<script src="lib/CustomButton.js"></script>

自定义按钮显示在表格中,但无法转发事件。似乎该组件无法在其自身范围之外进行通信。

4

3 回答 3

1

您的自定义格式化程序返回的字符串将被处理为“普通”HTML,因此 Svelte 语法不再可用......即on:click是 Svelte 语法,不会被浏览器处理。

我不是自定义元素专家,但不幸的是,根据其他人的说法,您尝试做的事情是不可能的。也就是说,您不能仅从 HTML 中在自定义元素上注册自定义事件侦听器。您必须从 JS 中执行此操作。像这样的东西:

    <script>
      document.querySelector('custom-button')
        .addEventListener('my-event', e => {
          console.log(e.detail)
        })
    </script>

此外,请注意,来自 Svelte 中自定义元素的事件目前受到一些限制(请参阅此问题)。

因此,为了为您的自定义元素设置自定义事件,您必须使用某种解决方法。例如,这是一个将触发上述代码段中的侦听器的组件:

<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 元素上的 click 或 keydown ......

因此,看来这应该适合您:

return '<ul class="actions_row"><li><custom-button onclick="handleClick">Edit</custom-button></li></ul>';

注意:onclick="handleClick"而不是on:click={handleClick}. 您现在处于标准浏览器领域,因此适用常规规则,就像您使用普通<button>...handleClick必须在范围内可用,等等。

于 2020-03-06T13:25:19.387 回答
0

发生这种情况的原因是因为您正在从格式化程序返回一个 HTML 字符串,这意味着任何 JS 绑定(例如单击事件处理程序)都将被剥离,作为将其转换为字符串的一部分。(单击函数绑定的上下文将丢失,因为该函数仅在写入字符串的函数中有效,而不是在解析字符串的位置)

为了保留绑定,您应该返回代表按钮的节点对象本身,而不仅仅是其 HTML,这样您的其他库添加到它的任何事件绑定都将保持不变。

于 2020-04-10T14:06:33.823 回答
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');
  });
});
于 2021-05-14T05:49:04.077 回答