〖大前端 - 基础入门三大核心之JS篇㊶〗- DOM事件传播和事件监听方法addEventListener()

  • 说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!
  • 作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。
  • 荣誉:2022年度博客之星Top4、2023年度超级个体得主、谷歌与亚马逊开发者大会特约speaker、全栈领域优质创作者。



文章目录

  • [⭐ 事件传播](#⭐ 事件传播)
  • [⭐ addEventListener()方法。](#⭐ addEventListener()方法。)

⭐ 事件传播

先来思考一个问题:

当页面的盒子有嵌套时,如果盒子都设置了同样的事件监听,那么事件监听触发的顺序是什么样的呢?比如下面图中,三个盒子都设置了onclick事件监听,当鼠标点击最内侧的盒子时,会触发三个盒子的onclick事件,那这三个事件触发的顺序是怎样的?

我们编写代码来验证一下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1 {
            width: 142px;
            height: 142px;
            border: 1px solid #000;
            padding: 20px;
        }
        #box2 {
            width: 102px;
            height: 102px;
            border: 1px solid #000;
            padding: 20px;
        }
        #box3 {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBox3 = document.getElementById('box3');

        oBox1.onclick = function () {
            console.log('鼠标单击box1');
        };
        oBox2.onclick = function () {
            console.log('鼠标单击box2');
        };
        oBox3.onclick = function () {
            console.log('鼠标单击box3');
        };
    </script>
</body>
</html>

这种从内到外触发事件的过程就是事件传播的过程。

但事实上,真实的事件传播并不仅仅是由内到外的,而是先从外到内,然后再从内到外,那为什么结果只有从内到外的呢?这是因为onxxx事件监听只能监听后面的一段过程,即从内到外的过程。

**事件的传播:**DOM规定事件传播的方向是先从外到内,再从内到外

从外到内的过程为捕获阶段(capturing phase),从内到外的过程为冒泡阶段(Bubbing phase)

那么问题来了,如何才能监听到捕获阶段呢?这就用到第二种事件监听方法------addEventListener()方法。

在DOM更新过程中,事件监听分成两个级别:DOM0级事件监听和DOM2级事件监听。一开始只有DOM0级事件监听,只能监听到冒泡阶段;在DOM2中新增加了addEventListener()方法,可以监听到捕获和冒泡两个阶段。之所以没有DOM1级,是因为DOM1中没有对事件监听的方法进行更新修改。

⭐ addEventListener()方法。

addEventListener()方法的示例代码:

js 复制代码
oBox.addEventListener('click', function(){   //click表示鼠标单击
    //事件处理函数代码
}, true);//true表示监听捕获阶段,false表示监听冒泡阶段

上面的例子中,用addEventListener()方法监听整个事件传播的过程,代码如下:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box1 {
            width: 142px;
            height: 142px;
            border: 1px solid #000;
            padding: 20px;
        }
        #box2 {
            width: 102px;
            height: 102px;
            border: 1px solid #000;
            padding: 20px;
        }
        #box3 {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
        }
    </style>
</head>
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBox3 = document.getElementById('box3');

        oBox1.addEventListener('click', function () {
            console.log('我是box1的捕获阶段');
        }, true);
        oBox2.addEventListener('click', function () {
            console.log('我是box2的捕获阶段');
        }, true);
        oBox3.addEventListener('click', function () {
            console.log('我是box3的捕获阶段');
        }, true);
        oBox1.addEventListener('click', function () {
            console.log('我是box1的冒泡阶段');
        }, false);
        oBox2.addEventListener('click', function () {
            console.log('我是box2的冒泡阶段');
        }, false);
        oBox3.addEventListener('click', function () {
            console.log('我是box3的冒泡阶段');
        }, false);
    </script>
</body>
</html>

上述代码中,需要注意的是,触发事件监听的顺序跟代码书写的顺序没有关系的,新手可能会误以为两者有关系,我们把捕获和冒泡的代码顺序调一下也不会影响事件传播顺序:

还需注意的是,如果给元素设置相同的两个或多个同名事件时,DOM0级的事件监听后面写的会覆盖先写的;而DOM2级的会按顺序执行。示例代码:

html 复制代码
<body>
    <div id="box1">
        <div id="box2">
            <div id="box3"></div>
        </div>
    </div>
    <script>
        var oBox1 = document.getElementById('box1');
        var oBox2 = document.getElementById('box2');
        var oBox3 = document.getElementById('box3');

        oBox2.onclick = function () {   //这个事件监听会被后面的覆盖
            console.log('A');
        };
        oBox2.onclick = function () {
            console.log('B');
        };

        oBox2.addEventListener('click', function () {   //不会被覆盖
            console.log('C');
        },true)
        oBox2.addEventListener('click', function () {   //不会被覆盖
            console.log('D');
        },true)
    </script>
</body>
相关推荐
小林ixn6 小时前
别再背八股了!从 5 个真实场景彻底搞懂 JavaScript 的 this
javascript
爱读源码的大都督6 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端
爱勇宝6 小时前
Claude Code 被曝暗藏“隐形检测”代码:封代理不是最可怕的,可怕的是你根本不知道它在干什么
前端·后端·程序员
小牛不牛的程序员6 小时前
我用 Claude Code 半天撸完了一个完整网站,AI 编程到底提升了多少效率?
前端
东风破_6 小时前
JavaScript 面试常考的字符串算法:从反转字符串到回文判断
前端·javascript
巴勒个啦6 小时前
D3.js 入门实战:用力导向图可视化项目依赖关系
javascript
ITOM运维行者7 小时前
从零搭建企业级服务器监控体系:踩坑实录与架构设计
前端·后端
monologues7 小时前
深入 Vue 3 源码:响应式系统的精妙设计与编译优化
前端
hunterandroid7 小时前
Paging 3 分页:从手动分页到声明式加载
前端
用户4099322502127 小时前
Vue状态管理入门第四章:组合式store和SSR风险
前端·vue.js·后端