4

可能重复:
什么是事件冒泡和捕获

我刚刚了解到在 JS 中我们有两种事件类型:Capture 和 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中冒泡默认事件顺序?那么在哪种情况下会使用捕获(自上而下)?

4

2 回答 2

4

想象一下,你有一个看起来像这样的 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

那么什么时候让祖先知道在实际点击按钮之前发生的点击是有益的呢?
好问题!

我敢肯定,有人会想出一些东西,而不仅仅是通过隐藏他们应该点击的东西来让人们痛苦的真正愚蠢的方式。

但道德是你明确要求它(设置.addEventListenerto的第三个参数true)。
此外,oldIE 等根本不支持捕获。

这不是一般应该使用的东西。

于 2012-11-06T22:11:56.127 回答
2

默认事件顺序是特定于浏览器的

事件捕获:外部元素的事件处理程序首先触发,内部元素的事件处理程序最后触发。

事件冒泡:内部元素的事件处理程序首先触发,外部元素的事件处理程序最后触发。

这两种事件秩序是完全对立的。Explorer 仅支持事件冒泡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();
}

http://www.quirksmode.org/js/events_order.html

于 2012-11-06T21:12:15.893 回答