从包含 Web 组件的插槽内容中捕获事件

stw*_*sel 6 javascript web-component dom-events custom-element

我有一个简单的 Web 组件,其中包含<slot>. 它处理表单数据,并且在我内部有 UI 元素可以发出数据更改/选定事件。我想知道 web 组件如何对插槽内容发出的事件做出反应。沿着这些路线的东西:

<my-form-handler>
     <my-player-selector player-id="master"></my-player-selector>
     <my-player-selector player-id="challenger"></my-player-selector>
     <my-weapons-selector default="sword"></my-weapons-selector>
</my-form-handler>
Run Code Online (Sandbox Code Playgroud)

我知道我可以编写<my-form-handler ondataSelected="someFunction">假设选择器元素发出dataSelected事件。但这需要代码位于包含页面而不是 my-form-handler 中。

我没有使用任何框架(Vue、Angular、React),只是普通的 JS。

Sup*_*arp 6

您可以在自定义元素中定义或方法中<my-form-handler>的处理程序。constructor()connectedCallback()

customElements.define( 'my-form-handler', class extends HTMLElement {
    conectedCallabck() {
        this.addEventListener( 'dataSelected', dsHandler )
   
        function dsHandler( ev ) {
             console.log( ev.type, ev.target.textContent )
        }
    }
} )
Run Code Online (Sandbox Code Playgroud)

当然,如果您希望this引用自定义元素对象,您可以使用箭头函数:

let dsHandler = ev => {
    console.log( ev.type, ev.target.textContent )
}
this.addEventListener( 'dataSelected', dsHandler )
Run Code Online (Sandbox Code Playgroud)

您还可以内联定义处理程序:

this.addEventListener( 'dataSelected', ev => 
    console.log( ev.type, ev.target.textContent )
)
Run Code Online (Sandbox Code Playgroud)

注意:如果您希望事件处理程序成为自定义元素方法,则需要使用bind(this)以确保它仍然可以访问自定义元素对象。

customElements.define( 'my-form-handler', class extends HTMLElement {
    conectedCallabck() {
        this.addEventListener( 'dataSelected', this.dsHandler.bind( this ) )
    }
    dsHandler( ev ) {
        console.log( 'recever: %s / emitter: %', this.localName, ev.target.textContent )
    }
} )
Run Code Online (Sandbox Code Playgroud)

或者,您可以在handleEvent()界面的帮助下选择集中式解决方案:

1将自定义元素本身设置为侦听器:

this.addEventListener( 'dataSelected', this )

2实现handleEvent()方法:

handleEvent( ev ) {
    switch( ev.type ) {
        case 'dataSelected':
            console.log( 'recever: %s / emitter: %', this.localName, ev.target.textContent )
            break
   }
}
   
Run Code Online (Sandbox Code Playgroud)

下面是一个正在运行的代码段:

customElements.define( 'my-form-handler', class extends HTMLElement {
    conectedCallabck() {
        this.addEventListener( 'dataSelected', dsHandler )
   
        function dsHandler( ev ) {
             console.log( ev.type, ev.target.textContent )
        }
    }
} )
Run Code Online (Sandbox Code Playgroud)
let dsHandler = ev => {
    console.log( ev.type, ev.target.textContent )
}
this.addEventListener( 'dataSelected', dsHandler )
Run Code Online (Sandbox Code Playgroud)