如何在 Web Components 中捕获自定义事件?
How to catch custom events in Web Components?
为了让 Web 组件相互通信,我使用了自定义事件。让我们想象一下:
WebComponentA 使用或包含 WebComponentB,它在单击按钮时发送 CustomEvent(气泡:真,组合:真)。如果 WebComponentB 发送此事件,WebComponentA 想要执行某些操作。
我应该如何在 WebComponentB 中调度事件?
window.dispatchEvent(customEvent);
或
this.shadowRoot.dispatchEvent(customEvent);
我应该如何捕捉 WebComponentA 中的事件?
window.addEventListener(custom-event, () => {
);
或
this.shadowRoot.addEventListener(custom-event, () => {
);
我应该考虑使用一个或另一个有什么负面影响吗?
谢谢!
使用 bubble: true, composed: true
在组件本身上调度事件,这样事件就会冒泡到任何监视它的东西。当您非常具体地希望有很多可预测性和共享状态时,我的意思是这确实需要紧密耦合,那么只需在全局 self
(即浏览器中的 window
)上编排事件。这里有一些我希望有所帮助的随机例子,他们所做的只是为了展示一个例子而相对无用。总体想法是在有意义的情况下松散地耦合事物,事件只是传递与状态变化相关的消息。组件可以始终是完全隔离的,无论它在什么上下文中运行,都可以单独关注它对该信息的处理(准备和接收模型——这是功能模式高度适用的地方)。如果需要更多细节或令人困惑,请随意拼写出来,我们可以尽力提供帮助。
另请注意,因为我没有设置任何 shadowRoot,所以组合标志在此示例中根本没有用。
广泛地说:
全局:self
(window
的同义词或其他上下文中的工人);在这里协调旨在紧密耦合许多事物的事件——当需要非常具体的协调系统时,它是迄今为止最简单的组织方案;对于这种情况,只需在此处收听和分发事件即可;在 connectedCallback
和 disconnectedCallback
中添加和删除事件侦听器。然后要么用冒泡发送到任何地方,要么直接 self.dispatchEvent('type', {detail:...})
并且不再需要冒泡等。
节点:在树的任何级别,当组件具有任何状态或任何类型的事件时,处理场景并创建适当的消息作为 event.detail
和一个合理的名称作为 event.type
,然后从处理该逻辑的节点分派它。其他节点——在其自身上作为父节点等——可以监视 event.bubble
向上,并且当从影子节点调度时,这些事件可以使用 composed:true
标志以允许事件在 shadowRoot 之外继续.或者该元素可以处理内部事件并分派适合该类型的新型事件和负载。
<my-global>my global </my-global>
<my-aye> aye (parent)
<my-bee> bee (child) </my-bee>
</my-aye>
<my-bee> bee </my-bee>
function eventdetails(event){
const {type, detail} = event;
console.log({type, detail, self:this, path: event.composedPath(), event});
}
customElements.define('my-global', class MyGlobalWatch extends HTMLElement{
constructor(){
super();
this.global = this.global.bind(this);
}
global(event){
eventdetails.call(this, event);
}
connectedCallback(){
self.addEventListener('global', this.global);
}
disconnectedCallback(){
self.removeEventListener('global', this.global);
}
});
customElements.define('my-aye', class MyAye extends HTMLElement{
constructor(){
super();
this.addEventListener('hi-aye', this.handle);
this.addEventListener('hi-bee', this.handle);
}
handle(event){
eventdetails.call(this, event);
if(event.type === 'hi-bee'){
self.dispatchEvent(new CustomEvent('global', {detail: event.detail, cancelable: true, composed: true, bubbles: false}));
}
}
});
customElements.define('my-bee', class MyBee extends HTMLElement{
constructor(){
super();
this.addEventListener('hi-aye', this.handle);
this.addEventListener('hi-bee', this.handle);
this.ticker = this.ticker.bind(this);
}
handle(event){
eventdetails.call(this, event);
}
ticker(){
// 3 events of the same type, different configuration
this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> -composed +bubbles'}, cancelable: true, composed: false, bubbles: true}));
this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> +composed +bubbles'}, cancelable: true, composed: true, bubbles: true}));
this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> -composed -bubbles'}, cancelable: true, composed: false, bubbles: false}));
this.dispatchEvent(new CustomEvent('hi-bee', {detail: {stuff:'things'}, cancelable: true, composed: true, bubbles: true}));
this._timer = setTimeout(this.ticker, 1234);
}
connectedCallback(){
this.ticker();
}
disconnectedCallback(){
clearTimeout(this._timer);
}
});
为了让 Web 组件相互通信,我使用了自定义事件。让我们想象一下:
WebComponentA 使用或包含 WebComponentB,它在单击按钮时发送 CustomEvent(气泡:真,组合:真)。如果 WebComponentB 发送此事件,WebComponentA 想要执行某些操作。
我应该如何在 WebComponentB 中调度事件?
window.dispatchEvent(customEvent);
或
this.shadowRoot.dispatchEvent(customEvent);
我应该如何捕捉 WebComponentA 中的事件?
window.addEventListener(custom-event, () => {
);
或
this.shadowRoot.addEventListener(custom-event, () => {
);
我应该考虑使用一个或另一个有什么负面影响吗?
谢谢!
使用 bubble: true, composed: true
在组件本身上调度事件,这样事件就会冒泡到任何监视它的东西。当您非常具体地希望有很多可预测性和共享状态时,我的意思是这确实需要紧密耦合,那么只需在全局 self
(即浏览器中的 window
)上编排事件。这里有一些我希望有所帮助的随机例子,他们所做的只是为了展示一个例子而相对无用。总体想法是在有意义的情况下松散地耦合事物,事件只是传递与状态变化相关的消息。组件可以始终是完全隔离的,无论它在什么上下文中运行,都可以单独关注它对该信息的处理(准备和接收模型——这是功能模式高度适用的地方)。如果需要更多细节或令人困惑,请随意拼写出来,我们可以尽力提供帮助。
另请注意,因为我没有设置任何 shadowRoot,所以组合标志在此示例中根本没有用。
广泛地说:
全局:
self
(window
的同义词或其他上下文中的工人);在这里协调旨在紧密耦合许多事物的事件——当需要非常具体的协调系统时,它是迄今为止最简单的组织方案;对于这种情况,只需在此处收听和分发事件即可;在connectedCallback
和disconnectedCallback
中添加和删除事件侦听器。然后要么用冒泡发送到任何地方,要么直接self.dispatchEvent('type', {detail:...})
并且不再需要冒泡等。节点:在树的任何级别,当组件具有任何状态或任何类型的事件时,处理场景并创建适当的消息作为
event.detail
和一个合理的名称作为event.type
,然后从处理该逻辑的节点分派它。其他节点——在其自身上作为父节点等——可以监视event.bubble
向上,并且当从影子节点调度时,这些事件可以使用composed:true
标志以允许事件在 shadowRoot 之外继续.或者该元素可以处理内部事件并分派适合该类型的新型事件和负载。<my-global>my global </my-global> <my-aye> aye (parent) <my-bee> bee (child) </my-bee> </my-aye> <my-bee> bee </my-bee> function eventdetails(event){ const {type, detail} = event; console.log({type, detail, self:this, path: event.composedPath(), event}); } customElements.define('my-global', class MyGlobalWatch extends HTMLElement{ constructor(){ super(); this.global = this.global.bind(this); } global(event){ eventdetails.call(this, event); } connectedCallback(){ self.addEventListener('global', this.global); } disconnectedCallback(){ self.removeEventListener('global', this.global); } }); customElements.define('my-aye', class MyAye extends HTMLElement{ constructor(){ super(); this.addEventListener('hi-aye', this.handle); this.addEventListener('hi-bee', this.handle); } handle(event){ eventdetails.call(this, event); if(event.type === 'hi-bee'){ self.dispatchEvent(new CustomEvent('global', {detail: event.detail, cancelable: true, composed: true, bubbles: false})); } } }); customElements.define('my-bee', class MyBee extends HTMLElement{ constructor(){ super(); this.addEventListener('hi-aye', this.handle); this.addEventListener('hi-bee', this.handle); this.ticker = this.ticker.bind(this); } handle(event){ eventdetails.call(this, event); } ticker(){ // 3 events of the same type, different configuration this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> -composed +bubbles'}, cancelable: true, composed: false, bubbles: true})); this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> +composed +bubbles'}, cancelable: true, composed: true, bubbles: true})); this.dispatchEvent(new CustomEvent('hi-aye', {detail: {payload:'> -composed -bubbles'}, cancelable: true, composed: false, bubbles: false})); this.dispatchEvent(new CustomEvent('hi-bee', {detail: {stuff:'things'}, cancelable: true, composed: true, bubbles: true})); this._timer = setTimeout(this.ticker, 1234); } connectedCallback(){ this.ticker(); } disconnectedCallback(){ clearTimeout(this._timer); } });