【发布时间】:2019-07-28 21:12:31
【问题描述】:
我查看了 jQuery 的源代码,以了解它们如何在委派事件侦听器中实现对 event.stopPropagation() 的支持,即 document.on(event, element...),但似乎无法让我自己的 vanilla JS 实现完全工作。
我尝试在我的方法中覆盖原生 event.stopPropagation() 以简单地在事件本身上设置一个 event.propagationStopped,并在决定事件是否应该传播到其父级时寻找它。
当停止传播的事件侦听器附加在其他事件侦听器之前时,这有效,但是当它以相反的顺序附加时它不起作用,这在 jQuery 的实现中按预期工作。
function delegate(type, selector, callback) {
document.addEventListener(type, function(event) {
event.stopPropagation = function() {
event.propagationStopped = true;
};
var element = event.target, found;
while (element && element.parentNode) {
if (element.matches(selector)) {
callback.call(element, event);
}
if (!event.propagationStopped) {
element = element.parentNode;
} else {
break;
}
}
});
}
delegate('click', '.overlay', function() {
console.log('Close overlay');
});
delegate('click', '.modal', function(e) {
e.stopPropagation();
console.log('Clicked inside modal, stopping propagation...');
});
我希望事件停止在所有事件侦听器中的进一步传播,而不管它们的附加顺序如何,而不是当前的行为。
【问题讨论】:
-
IIRC,jQuery 仅附加一个实际的 DOM 事件侦听器,并将回调存储在元素的数据属性中。然后当 DOM 事件触发时,它会自行完成所有的传播和顺序调用。
-
@Bergi 我也在考虑这个问题,但我希望有一种更简单的方法,因为我不确定如何存储这些(不想将任何东西附加到实际元素),也不知道如何决定它们应该以什么顺序被调用。
-
我会写一个答案来演示如何做到这一点。不知道有没有更好的办法,我也很好奇……
标签: javascript event-handling stoppropagation event-delegation event-propagation