StencilJs 中的冒泡事件没有正确的 event.target

Bubbled event in StencilJs does not have correct event.target

前段时间开始使用Stencil,今天做了一个事件冒泡的实验。

基本上,我点击了一个 child 元素并在其 parent 上收听了 mousedown。我期望 event.target 成为我的 child 组件。这非常简单,例如,如果我 运行 使用常规 DOM 元素(不是 Stencil)进行此测试,它都会按预期工作

DEMO

但在 Stencil 中 event.target 是 parent 元素。这是我所做的。我的 parent 组件如下所示:

@Component({
    tag: 'app-root',
    styleUrl: 'app-root.scss',
    shadow: true 
})
export class MyApp {
    @Listen('mousedown')
    onMousedown(event) {
         console.log(event.target, event.currentTarget);
    }

    render() {
        return (
            <div>
                <my-element></my-element>
           </div> );
   }
}

还有 child

@Component({
    tag: 'my-element',
    styleUrl: './my-element.scss',
    shadow: true
})
export class MyElement {
    @Listen('mousedown')
    onMouseDonw(e) {
        console.log(e.target);
    }

    render() {
       return ( <div>YO</div> );
    }
}

现在,正如我所说,当我单击 my-element 时,我首先看到 my-element 中的 console.log,这确认 event.targetmy-element .但随后事件到达其 parent 并且 event.target(还有 event.currentTarget)包含 app-root。我注意到,当我将 app-rootshadow 设置为 false 时,一切似乎都有效,但我不明白为什么,这是解决我的问题的唯一方法吗?

它被认为是阴影封装的一个特征DOM。原始目标被隐藏为“内部实现”,而是将事件重新定位到宿主元素。

当您在 MyApp 中使用 Listen 装饰器附加侦听器时,它将附加到组件的宿主元素,在本例中为 app-root

您可以使用 event.composedPath() 获取真实目标(IE 和旧版 Edge 不支持)。

或者您可以从组件中捕获事件并将其作为自定义事件重新发出并转发真实事件或目标元素:

export class MyApp {
    @Event() myMousedown: EventEmitter<MouseEvent>;

    handleElementMousedown = (event: MouseEvent) => {
        this.myMousedown.emit(event);
    }

    render() {
        return (
            <div>
                <my-element onMousedown={handleElementMousedown} />
           </div> );
   }
}
document
    .querySelector('app-root')
    .attachEventListener('my-mousedown', console.log);

(免责声明:此代码未经测试)