如您所知,事件通常在javascript中冒泡,因此首先执行触发事件的元素的事件处理程序,然后调用父元素的事件处理程序,依此类推。这种行为会导致我正在处理的项目出现一些问题,我宁愿将执行顺序颠倒过来。
我想出了一个使用超时的解决方案:
$(element).mouseover(function(){
var that = this;
setTimeout(function() {
//actual event handler, but references to "this" are replaced with "that"
},$(this).parents().length)
});
基本上,事件处理程序在短暂超时后执行,等待时间取决于DOM树中元素的深度: html元素的事件处理程序立即执行,body元素的事件处理程序在等待1ms后执行,依此类推。所以事件的执行顺序是相反的。
我的第一次测试结果是积极的,但我仍然不确定此解决方案是否存在任何问题或缺点。您如何看待这个解决方案?关于如何解决这些问题的其他想法也受到高度赞赏。
答案 0 :(得分:18)
反向事件冒泡称为捕获阶段。
将true
作为第3个参数传递给Event.addEventListener
,使其在捕获阶段触发
el.addEventListener("click", function () {
console.log("i run in capture");
}, true);
当然,它不会在传统平台上工作。您需要一个DOM3事件填充程序来模拟事件系统。随意为DOM-shim
做出贡献答案 1 :(得分:0)
我可以看到你的解决方案的一个巨大缺点是事实,对于每个处理过的事件,你必须从this
开始向上遍历DOM以建立父母的数量。
在每个事件处理程序中以这种方式遍历=低性能。
答案 2 :(得分:0)
你可以尝试模仿它,但可能会造成很多麻烦。
这是一个非常简单的例子(在jsfiddle上)。
我们的想法是聚合来自每个事件的回调,并在document
事件处理程序中以相反的顺序调用它们(我们也清除了我们的列表,以确保下次单击时有新的队列)。
<div id="a">
<div id="b">
<a href="/test">Click Me!</a>
</div>
</div>
var cb = [];
$(document).click(function(evt){
cb.unshift(function(){
console.log('document');
});
var i;
for(i=0; i<cb.length; ++i){
cb[i].call(null, evt);
}
cb = [];
});
$("#a").click(function(){
cb.unshift(function(){
console.log('div#a');
});
});
$("#b").click(function(){
cb.unshift(function(){
console.log('div#b');
});
});
$('a').click(function(evt){
cb.unshift(function(evt){
evt.preventDefault();
console.log('a');
});
});
也许你需要改变你的设计?您可以发布更多信息,为什么需要事件捕获?