是否可以使用目标对象分派精简的自定义事件?

Lon*_*ike 6 custom-events svelte

是否可以createEventDispatcher像本机浏览器事件一样使用目标对象调度 svelte 事件(使用 创建)?

即在处理程序端接收event.target.value而不是 event.detail。

hac*_*ape 6

是的,这是可能的,但涉及一些黑客行为。

您可以查看 svelte 源代码以了解事件调度的工作原理。我将概述关键部分如下。

假设我们有两个组件,InnerOuter

<!-- Inner.svelte -->
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
const dispatchFoo = () => dispatch('foo', 'bar')
</script>

<button on:click={dispatchFoo}>send</button>

<!-- Outer.svelte -->
<script>
import Inner from './Inner.svelte'
const handleFoo = (e) => { console.log('receive foo', e) }
</script>

<Inner on:foo={handleFoo}></Inner>
Run Code Online (Sandbox Code Playgroud)

如果您考虑一下,事件处理程序handleFoo是在 中创建的Outer,但实际上是在 中注册的Inner

检查编译后的 JS 代码,您将看到:

  1. inner.$$.callbacks["foo"]保存事件处理程序 [ src ]
  2. 当您单击按钮并调用 时dispatch,它只会读取inner.$$.callbacks["foo"]潜在的处理程序,如果找到,则使用CustomEvent参数 [ src ]调用它们

设置的唯一方法customEvent.target是使用 调度该自定义事件element.dispatchEvent(customEvent)。但并element.dispatchEvent没有在整个过程中使用。

解决方案(破解)

写你自己的createEventDispatcher

import { get_current_component } from 'svelte/internal'

function createEventDispatcher() {
  const component = get_current_component();
  return (type, target, detail) => {
    const callbacks = component.$$.callbacks[type];
    if (callbacks) {
      const event = new CustomEvent(type, { detail });
      // the key is to call `dispatchEvent` manually to set `event.target`
      target.dispatchEvent(event);
      callbacks.slice().forEach((fn) => {
        fn.call(component, event);
      });
    }
  };
}
Run Code Online (Sandbox Code Playgroud)

精简 REPL