javascript - 什么是事件冒泡和捕获?

标签 javascript dom-events event-bubbling

事件冒泡和捕获有什么区别?什么时候应该使用冒泡和捕获?

最佳答案

事件冒泡和捕获是 HTML DOM API 中事件传播的两种方式,当一个事件发生在另一个元素内的一个元素中,并且两个元素都注册了该事件的句柄时。事件传播模式在 which order the elements receive the event 中确定.

通过冒泡,事件首先由最里面的元素捕获和处理,然后传播到外部元素。

通过捕获,事件首先被最外面的元素捕获并传播到内部元素。

捕获也称为“trickling”,这有助于记住传播顺序:

trickle down, bubble up

过去,Netscape 提倡事件捕获,而 Microsoft 则提倡事件冒泡。两者都是 W3C Document Object Model Events 的一部分标准(2000)。

IE < 9 使用only event bubbling ,而 IE9+ 和所有主要浏览器都支持两者。另一方面,performance of event bubbling may be slightly lower对于复杂的 DOM。

我们可以使用addEventListener(type,listener,useCapture)在冒泡(默认)或捕获模式下注册事件处理程序。要使用捕获模型,请将第三个参数传递为 true

示例

<div>
    <ul>
        <li></li>
    </ul>
</div>

在上面的结构中,假设在 li 元素中发生了单击事件。

在捕获模型中,事件将首先由 div 处理(div 中的单击事件处理程序将首先触发),然后在 ul,然后是目标元素的最后一个 li

在冒泡模型中,会发生相反的情况:事件将首先由 li 处理,然后由 ul 处理,最后由 div 元素。

欲了解更多信息,请参阅

在下面的示例中,如果单击任何突出显示的元素,您可以看到事件传播流的捕获阶段首先发生,然后是冒泡阶段。

var logElement = document.getElementById('log');

function log(msg) {
    logElement.innerHTML += ('<p>' + msg + '</p>');
}

function capture() {
    log('capture: ' + this.firstChild.nodeValue.trim());
}

function bubble() {
    log('bubble: ' + this.firstChild.nodeValue.trim());
}

function clearOutput() {
    logElement.innerHTML = "";
}

var divs = document.getElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
    divs[i].addEventListener('click', capture, true);
    divs[i].addEventListener('click', bubble, false);
}
var clearButton = document.getElementById('clear');
clearButton.addEventListener('click', clearOutput);
p {
    line-height: 0;
}

div {
    display:inline-block;
    padding: 5px;

    background: #fff;
    border: 1px solid #aaa;
    cursor: pointer;
}

div:hover {
    border: 1px solid #faa;
    background: #fdd;
}
<div>1
    <div>2
        <div>3
            <div>4
                <div>5</div>
            </div>
        </div>
    </div>
</div>
<button id="clear">clear output</button>
<section id="log"></section>

Another example at JSFiddle .

关于javascript - 什么是事件冒泡和捕获?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33181394/

相关文章:

javascript - 如何使用 node.js、sockets.io 和 redis 在已连接的客户端上触发事件?

javascript - 在 javascript 中更新后,我无法从后面的代码中获取 session 变量

javascript - Chrome 中的 Netflix 视频播放器 - 如何寻找?

jquery - 防止点击冒泡而不返回 false

javascript - 奇怪的冒泡问题

javascript - 集群 Node 应用程序时 Socket.io websocket 授权失败

JavaScript (Node.js) 仅在 Linux Node 上将字符串内容解释为对象

javascript - Canvas 跟随光标

javascript - 单击事件在 IE/Firefox 中触发,但 Chrome 正在放弃事件分配

javascript - 如果我不测试被动事件监听器支持会发生什么?