其他两个答案+1,事件是最好的,因为组件松散耦合
另见:https ://pm.dartus.fr/blog/a-complete-guide-on-shadow-dom-and-event-propagation/
请注意,在detail
自定义事件中,您可以发送您想要的任何内容。
事件驱动的函数执行:
所以我使用(伪代码):
定义单人纸牌/Freecell 游戏的元素:
-> game Element
-> pile Element
-> slot Element
-> card element
-> pile Element
-> slot Element
-> empty
当一张卡片(由用户拖动)需要移动到另一堆时,
它发送一个事件(将 DOM 冒泡到游戏元素)
//triggered by .dragend Event
card.say(___FINDSLOT___, {
id,
reply: slot => card.move(slot)
});
注: reply
是一个函数定义
因为所有___FINDSLOT___
在游戏元素中被告知要监听事件的堆......
pile.on(game, ___FINDSLOT___, evt => {
let foundslot = pile.free(evt.detail.id);
if (foundslot.length) evt.detail.reply(foundslot[0]);
});
只有一堆匹配的evt.detail.id
响应:
!!!通过执行card
发送的函数evt.detail.reply
并获得技术:该功能在pile
范围内执行!
(以上代码为伪代码!)
为什么?!
可能看起来很复杂;
重要的部分是pile
元素不耦合到元素中的.move()
方法card
。
唯一的耦合是事件的名称:___FINDSLOT___
!!!
这意味着card
始终处于控制之中,并且相同的 Event(Name)可用于:
- 卡可以去哪里?
- 最佳位置是什么?
- 河 牌中哪张牌
pile
会成为葫芦?
- ...
在我的电子元素代码中,两者pile
都没有耦合evt.detail.id
,
CustomEvents 只发送函数
.say()
并且.on()
是我的自定义方法(在每个元素上dispatchEvent
)addEventListener
我现在有一些可用于创建任何纸牌游戏的元素
不需要任何库,编写自己的“消息总线”
我的element.on()
方法只是围绕addEventListener
函数包裹几行代码,因此可以轻松删除它们:
$Element_addEventListener(
name,
func,
options = {}
) {
let BigBrotherFunc = evt => { // wrap every Listener function
if (evt.detail && evt.detail.reply) {
el.warn(`can catch ALL replies '${evt.type}' here`, evt);
}
func(evt);
}
el.addEventListener(name, BigBrotherFunc, options);
return [name, () => el.removeEventListener(name, BigBrotherFunc)];
},
on(
//!! no parameter defintions, because function uses ...arguments
) {
let args = [...arguments]; // get arguments array
let target = el; // default target is current element
if (args[0] instanceof HTMLElement) target = args.shift(); // if first element is another element, take it out the args array
args[0] = ___eventName(args[0]) || args[0]; // proces eventNR
$Element_ListenersArray.push(target.$Element_addEventListener(...args));
},
.say( )
是单线:
say(
eventNR,
detail, //todo some default something here ??
options = {
detail,
bubbles: 1, // event bubbles UP the DOM
composed: 1, // !!! required so Event bubbles through the shadowDOM boundaries
}
) {
el.dispatchEvent(new CustomEvent(___eventName(eventNR) || eventNR, options));
},