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

Jea*_*eri 2 javascript web-component shadow-dom stenciljs

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

基本上,我单击一个子元素并监听其父元素的mousedown。我所期望的是那event.target是我的子组件。这非常简单,例如,如果我使用常规 DOM 元素(而不是 Stencil)运行此测试,那么一切都会按预期工作

在此输入图像描述

演示版

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

@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> );
   }
}
Run Code Online (Sandbox Code Playgroud)

还有孩子

@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> );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,正如我所说,当我单击 时my-element,我首先看到console.logfrom my-element,这证实了这event.targetmy-element。但随后该事件到达其父级并且event.target(但也event.currentTarget)包含app-root。我注意到,当我设置shadowfalseof my时app-root,一切似乎都有效,但我不明白为什么,这是解决我的问题的唯一解决方案吗?

Sim*_*sch 5

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

当您将侦听器附加Listen到 中的装饰器时MyApp,它会附加到组件的宿主元素,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> );
   }
}
Run Code Online (Sandbox Code Playgroud)
export class MyApp {
    @Event() myMousedown: EventEmitter<MouseEvent>;

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

    render() {
        return (
            <div>
                <my-element onMousedown={handleElementMousedown} />
           </div> );
   }
}
Run Code Online (Sandbox Code Playgroud)

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