Components

事件处理程序

编辑此页面

事件处理程序是指为响应浏览器中发生的特定事件而调用的函数,例如当用户单击某个元素时。

Solid 提供了两种向浏览器添加事件监听器的方法:

  • on:__: 向 element 添加事件监听器。这也称为原生事件(native event)
  • on__: 将事件监听器添加到 document 并将其分派到 element 。这也被称为委托事件(delegated event)。

使用事件

要添加事件处理程序,在事件名称前加上 onon:前缀:

// delegated event
<button onClick={handleClick}>Click me</button>
// native event
<div on:scroll={handleScroll}>... very long text ...</div>

委托事件不区分大小写,因此在 Solid 中使用委托事件处理程序可以使用驼峰式或全部小写形式编写。请注意,虽然委托事件可以用两种方式编写,但原生事件区分大小写

<button onclick={handleClick}>Click me</button>

对于其他事件,例如自定义事件或您不希望被代理的事件,使用 on:属性将原样添加事件处理器,这就是事件处理器区分大小写的原因:

<button on:Custom-Event={handleClick}>Click me</button>

对于使用 on:的标准或自定义事件的类型,TypeScript 页面有一个关于事件处理器的部分。


绑定事件

要优化事件处理程序,您可以传递一个数组替代原本的函数作为事件处理程序,此时传递到数组的第二个条目将作为处理程序的第一个参数:

const handler = (data, event) => {
console.log("Data:", data, "Event:", event);
};
<button onClick={[handler, "Hello!"]}>Click Me</button>;

在这个例子中 ,点击按钮时,Hello!字符串将作为 handler 函数中的 data 参数传递。

通过这种方式绑定事件,Solid 避免了使用 JavaScript bind 方法造成的额外闭包开销。

动态处理程序

事件处理程序不是响应式系统的一部分,如果您将处理程序作为信号传递,它将不会响应信号的更改。换句话说,事件不会动态更新,并且绑定也不是响应式。这是因为添加和删除监听器是一项资源密集型任务。

由于事件处理程序的调用方法类似于标准函数,因为你可以将它们设计为在需要时调用响应式资源。

在下面的例子中,handleClick表示 props 具有调用任何函数的灵活性。因为不需要这些函数是响应式的:

<div onClick={() => props.handleClick?.()} />

事件委托

Solid 没有将事件监听器添加到每个单独的元素,而是通过 on__ 的形式使用合成事件委托。在这种方法中,事件监听器将添加到 document 元素,并在相关元素冒泡时将事件分派给它们。

通过将事件监听器的数量保持在最低限度,可以更有效地捕获事件。当处理大量元素(例如表格或列表)时特别有用。

clickinputkeydown 等受支持的事件只是以这种方式优化的几个示例。要查看完整列表,请参阅下面的委托事件列表

如果您需要将事件监听器添加到 Solid 的事件委托不支持的元素(例如自定义元素,%20you%20can%20use%20the%20on:__中的自定义事件),则可以使用 on:__ 形式。

<div on:customEvent={handleCustomEvent} />

事件委托注意事项

虽然事件委派提供了一些性能增强,但也需要权衡。

事件委托是为通过 JSX 树而不是 DOM 树传播事件而设计的。这可能与之前对事件如何运行和流动的预期不同。

需要记住的一些事情包括:

  • 委托事件监听器针对每个事件类型都添加一次,并处理该类型的所有未来事件。这意味着即使添加事件监听器的元素及其处理程序被删除,委托事件监听器仍保持活动状态。例如,如果 div 监听 mousemove 并随后被删除,mousemove 事件仍将分派到 document,以防还有另一个元素也在监听鼠标移动。
<div onMouseMove={handleCustomEvent} />
  • event.stopPropagation() 无法按预期工作,因为事件添加到 document 而不是 element

对于此类情况,建议使用原生事件。例如在接下来的例子中,使用原生事件将阻止事件到达 div native 处理程序,而委托事件则不能。

onMount(() => {
ref.addEventListener("click", () => {
console.log("div native");
});
});
<div ref={ref}>
<button
onClick={(event) => {
event.stopPropagation();
console.log("button");
}}
>
button
</button>
</div>;
Console output
// Button clicked
div native
button

您可以在 Solid Playground 中查看此示例

但如果将 button 改为使用原生事件:

// ...
<button
on:click={(event) => {
event.stopPropagation();
console.log("button");
}}
>
button
</button>
// ...
Console output
// Button clicked
button

您可以在 Solid Playground 中查看此示例。

  • Portals 按照组件树而不是 DOM 树传播事件,这使得它们更易于使用。这意味着当 Portal 添加到 body 时,任何事件都会传播到 container
<div class="container" onInput={() => console.log("portal key press")}>
<Portal mount={document.body}>
<input onInput={() => console.log("input key press")} />
</Portal>
</div>

委托事件列表

您可以在我们的源代码中查看此列表(请参阅 DelegatedEvents )。

报告此页面问题