我刚刚了解到,在JS中我们有两种事件类型:Capture和Bubble。可以使用Bubble来避免将eventListener附加到所有子节点;而是仅将侦听器附加到父级并让它检查目标。听起来很酷。我尝试了这个例子:
<div id="parent-list">
<span>span1</span>
<span class='target'>span2</span>
<span>span3</span>
<span>span4</span>
</div>
<script type="text/javascript">
document.getElementById('parent-list').addEventListener('click',function(e){
if( e.target && e.target.nodeName=='SPAN' ){
var classes = e.target.className.split(' ');
for(var i=0; i<classes.length; ++i){
if( classes[i]=='target' ){
alert('Bingo! you hit the target.');
}
}
}
});
</script>
但是我没有把任何听众都附在孩子的跨度上。然而,他们身上的事件正在冒泡!那么在JS中冒泡默认事件顺序是什么?然后在哪种情况下使用捕获(自上而下)?
答案 0 :(得分:3)
想象一下,你的html看起来像这样:
<div id="grandparent">
<div id="parent">
<button id="target"></button>
</div>
</div>
看起来像这样的JS:
function sayGrandpa (evt) { console.log("Grandpa"); }
function sayClicked (evt) { console.log("Clicked"); }
var grandparent = document.getElementById("grandparent"),
target = document.getElementById("target");
grandparent.addEventListener("click", sayGrandpa, false);
target.addEventListener("click", sayClicked, false);
Bubbling vs Capture与你想要的东西没有任何关系,因为在两种情况下(在W3C兼容的浏览器上),你可以使用事件监听器附加到父级,监听事件被孩子触发。
不同之处在于冒泡假设事件链从目标开始,并通过父母链回升,就像在地面零点引爆的炸弹,并向外发出冲击波。
捕获从window
(或<html>
)开始,然后转到目标元素。
因此,当您使用冒泡(更像是涟漪)时,任何在元素上直接设置的函数都会先发生,而任何 委派 附着在祖先身上的功能随着涟漪回到链条上而发生。
当您使用捕获时,附加到祖先的任何 委派的 函数都会在元素上发生事件之前发生。
因此,在grandparent
之前,target
元素知道点击次数。
所以,当你问到事情发生的顺序时,情况非常明显:
在grandparent
上设置 捕获 的事件,并在grandparent
上设置第二个事件 冒泡 ,并在target
上设置一个事件,订单将是:
captured grandparent
target
bubbled grandparent
那么,当实际被点击的按钮出现之前,让祖先知道发生了点击是否有益? 好问题!
我确信有人可以想到一些不仅仅是通过隐藏他们应该点击的东西让人们痛苦的真正方式。
但道德是你明确要求它(将.addEventListener
的第三个参数设置为true
)。
此外,oldIE和其他人根本不支持捕获。
这不是一般应该使用的东西。
答案 1 :(得分:2)
默认事件顺序为浏览器特定。
事件捕获:外部元素的事件处理程序首先触发,内部元素的事件处理程序最后触发。
事件冒泡:内部元素的事件处理程序首先触发,外部元素的事件处理程序最后触发。
两个事件订单完全相反。 资源管理器仅支持 事件冒泡。 Mozilla,Opera 7和Konqueror都支持。年长 Opera和iCab都不支持。
在Microsoft模型中,您必须将事件的cancelBubble
属性设置为true。
window.event.cancelBubble = true
在W3C模型中,您必须调用事件的stopPropagation()
方法。
e.stopPropagation()
function doSomething(e)
{
if (!e) var e = window.event;
e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation();
}