事件冒泡

事件流是网页元素接受事件的顺序,”DOM2 级事件“规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。首先发生的事件捕获,为捕获事件提供机会;然后是实际的目标接受事件;最后一个阶段是事件冒泡阶段,可以在这个阶段对事件做出相应。虽然捕获阶段在规定中规定不允许响应事件,但是实际上还是会执行,所以又两次机会获取到目标对象。

btn.addEventListener(eventType, function () {}, false);
// 第一个参数为事件名
// 第二个为事件处理程序
// 第三个为布尔值,true为事件捕获阶段调用事件处理程序,false为事件冒泡阶段调用事件处理程序,默认为false

来个例子:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>事件冒泡</title>
    </head>
    <body>
        <div>
            <button id="btn">按钮</button>
        </div>
    </body>
</html>
<script type="text/javascript">
    var btn = document.getElementById('btn');
    btn.addEventListener(
        'click',
        function () {
            alert('事件捕获');
        },
        true,
    );
    btn.addEventListener(
        'click',
        function () {
            alert('事件冒泡');
        },
        false,
    );
</script>

依次弹出”事件捕获“和”事件冒泡“

如果反过来写

var btn = document.getElementById('btn');
btn.addEventListener(
    'click',
    function () {
        alert('事件冒泡');
    },
    false,
);
btn.addEventListener(
    'click',
    function () {
        alert('事件捕获');
    },
    true,
);

依次弹出则是:”事件冒泡“和”事件捕获“。

所以我们可以总结出:如果一个事件中同时有”冒泡“和”捕获“,那么就按照代码的书写顺序来执行

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>事件冒泡</title>
    </head>
    <body>
        <div>
            <p id="parEle">
                我是父元素
                <span id="sonEle">我是子元素</span>
            </p>
        </div>
    </body>
</html>
<script type="text/javascript">
    var sonEle = document.getElementById('sonEle');
    var parEle = document.getElementById('parEle');

    parEle.addEventListener(
        'click',
        function () {
            alert('父级 冒泡');
        },
        false,
    );
    parEle.addEventListener(
        'click',
        function () {
            alert('父级 捕获');
        },
        true,
    );

    sonEle.addEventListener(
        'click',
        function () {
            alert('子级冒泡');
        },
        false,
    );
    sonEle.addEventListener(
        'click',
        function () {
            alert('子级捕获');
        },
        true,
    );
</script>

当容器元素及嵌套元素,既在捕获阶段又在冒泡阶段调用事件处理程序时:事件按 DOM 事件流的顺序执行事件处理顺序:

  • 父级捕获
  • 子级冒泡
  • 子级捕获
  • 父级冒泡

且当事件处于目标阶段时,事件调用顺序决定于绑定事件的书写顺序,按照上面例子,先调用冒泡阶段的事件,再调用捕获阶段的事件。一次 alert 出”子级冒泡“,”子级捕获“

参考资料

Last Updated:
Contributors: johan