在 StencilJS 组件中,带有“composed: false”的自定义事件仍可捕获外部阴影 DOM

Custom event with 'composed: false' still catchable outside shadow DOM in StencilJS component

提问人:saksonia 提问时间:7/27/2023 最后编辑:Ryan Waskiewiczsaksonia 更新时间:7/28/2023 访问量:83

问:

有人可以解释我的这种行为吗? 因此,在 Stencil js 中,我有使用具有 {composed: false} @Event装饰器发出的自定义事件。为什么即使我显式将 composed 设置为 false,我也能够在影子 DOM 之外捕获它?

来自 Stencil 文档组成?:布尔值; 一个布尔值,该值指示事件是否可以跨越影子 DOM 和常规 DOM 之间的边界冒泡。

组件.tsx

@Event() rate: EventEmitter<number>;

private handleStarClick(starIndex: number) {
    this.rate.emit(starIndex + 1);
}

索引.html

!DOCTYPE html>
<html dir="ltr" lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
    <link rel="stylesheet" href="/build/web-components.css" />
    <title>Stencil Component Starter</title>

    <script type="module" src="/build/web-components.esm.js"></script>
    <script nomodule src="/build/web-components.js"></script>

    <script type="module">
      document.querySelector("my-rating-stars").texts=["Terrible", "Bad", "Okay", "Good", "Excellent"];

****** LISTENING CUSTOM EVENT ******
      document.addEventListener("rate", (e) => console.log(e))
    </script>
  </head>
  <body>
     <my-rating-stars></my-rating-stars>
  </body>
</html>

由于我使用的是 composed set to false(这也是默认行为),因此我希望我只能在影子 DOM 范围内侦听该事件,但我可以从影子 DOM 之外侦听它。

事件 Web 组件 shadow-dom 模板 冒泡

评论


答:

0赞 G. Tranter 7/28/2023 #1

在您的示例代码中,composed 为 true - default 不是 false。但我认为你误解了模板事件发射器的工作原理。您的示例从影子根外部的主机发出一个事件,以便它到达文档。如果组件的影子 DOM 中有一个元素调度了 composed false 的事件,则该事件将停止在组件的影子根目录处传播,并且不会通过 接收。document.addEventListener()

例如:

render() {
    return <Host>
        <button onclick={event => event.target.dispatchEvent(
            new CustomEvent('nonComposedEvent', { composed: false, bubbles: true })
        )}>click me</button>
    </Host>;

因此,要使 Stencil 事件无法到达文档,该组件必须位于另一个组件的影子 DOM 中。@Event({composed: false})

评论

0赞 saksonia 7/29/2023
在我的示例中,我在 host 元素中有几个图标,单击时调用 handleStarClick 函数。如果我理解正确的话,我实际上是从阴影内部发出事件,因为我的图标在阴影内部。或者也许我完全误解了模板的工作原理。无论如何,我想我必须对模板如何与事件一起工作做更多的研究。感谢您的紧急回复!
0赞 G. Tranter 7/30/2023
不,您误解了事件和函数的工作原理。 是一个函数调用 - 与点击事件完全不同 - 它们仅通过您的逻辑连接。组件发出的自定义事件源自主机,而不是来自其他事件或元素。和功能基本上只是 JavaScript 的便利。this.rate.emit()@Eventemit()dispatchEvent()