第三天:js中的事件提高篇(事件流,事件对象,事件委托深层次理解)

前言

对于一个html网页来说,html是页面的骨架,css是页面的样式,而js则控制页面元素的行为。本篇我们将学习原生网页界面如何操作元素(监听并绑定事件)。并介绍事件流,事件对象,事件冒泡,以及事件委托这几个点。希望对读者的学习有帮助!

一,基础部分

1.1 js监听并绑定事件

请看以下代码:

    <button>方法监听注册事件</button>
    <script>
        var btn = document.querySelector('button');
        btn.addEventListener('click', function() {
            alert('22');
        })
        btn.addEventListener('click', function() {
            alert('22');
        })
    </script>

通过上述代码可了解:
第一步:绑定页面元素
第二步:监听器addEventListener

e.addEventListener('事件','回调函数') {}

这里需要注意的是,之前我们写简单的事件绑定,如e.onclick(),e.onmouse等,在新学习的这种写法中,事件写的内容要在原来的基础上把on去掉。

1.2 删除事件绑定

请看以下代码:

        divs[1].addEventListener('click', fn);
        function fn() {
            alert('22');
            divs[1].removeEventListener('click',fn);
        }

最开始给divs中索引为1的元素绑定了click事件,回调函数为fn。当点击fn后,先弹出‘22’模态框,然后取消了该元素的绑定事件。并执行新的回调函数。

二,事件流

2.1 事件流是什么

首先从字面上理解,事件流指从页面中接收事件的顺序。

我们知道,js是单线程的脚本语言(JavaScript是一种解释型的脚本语言,C、C++等语言先编译后执行,而JavaScript是在程序的运行过程中逐行进行解释。),当页面中的DOM元素触发事件,浏览器从Window开始从上往下遍历,来查找整个DOM元素。概括为事件发生时会在元素节点与根节点之间按照特定的顺序传播,路径所经过的所有节点都会收到该事件,这个传播过程即DOM事件流

2.2 事件流模型

事件流模型则可以很直观的从原理来为我们呈现事件流,事件流模型分为两个部分:分别是冒泡型事件流,捕获型事件流

我们知道,网页中元素很多,大部分元素都有父元素,也有部分元素有子元素,那么我们是不是可以把元素看成一棵树(DOM树):
在这里插入图片描述

冒泡型事件流:从DOM树的叶子到根,从下到上,范围从小到大遍历;
捕获型事件流:从DOM树的跟到叶子,从上到下,范围从大到小遍历。

2.3 捕获与冒泡具体示例

2.3.1 addEventListener的第三个参数

刚刚我们已经了解,js中addEventListener的用法。在介绍完冒泡与捕获后,向大家介绍第三个参数:具体格式如下

e.addEventListener('事件',‘回调函数’,第三个参数)

第三个参数是一个布尔值,默认为false,false对应的是冒泡,true代表的是捕获。

接下来我们利用以下结构来学习捕获与冒泡的具体实例:

    <div class="father">
        <div class="son"></div>
    </div>

在这里插入图片描述

2.3.1 捕获阶段

捕获阶段,addEventListener的第三个值是true,请看以下代码:

        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        }, true);//捕获阶段

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, true);//捕获阶段
         document.addEventListener('click', function() {
            alert('document');
        })

对子盒子,父盒子先进行获取,然后再绑定事件。理论上,点击son会弹出son模态框,点击father会弹出father模态框。但在捕获阶段:
点击father时没有任何问题:
在这里插入图片描述

点击son时却:
在这里插入图片描述在这里插入图片描述
原因:捕获型事件流:从DOM树的跟到叶子,从上到下,范围从大到小遍历。
点击父元素遍历顺序:father
点击子元素遍历顺序:father->son,所以点击子元素时会先出现父元素模态框,再出现子元素模态框。
至于为什么没有出现document的模态框,因为我们没有点document,点的是father所以从father开始遍历。

2.3.2 冒泡阶段

捕获阶段,addEventListener的第三个值是false(或者不写,因为默认false),请看以下代码:

        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        });
        var son = document.querySelector('.son');
        son.addEventListener('click', function() {
            alert('son');
        });

        document.addEventListener('click', function() {
            alert('document');
        })

点击father时:
在这里插入图片描述
在这里插入图片描述
点击son时:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原因:冒泡型事件流:从DOM树的叶子到根,从下到上,范围从小到大遍历
点击父元素遍历顺序:father->document;
点击子元素遍历顺序: son->father->document。

三,事件对象

3.1 事件对象是什么

div是一个盒子,为它绑定事件:

        var div = document.querySelector('div');
        div.addEventListener('click', function(event){
            console.log(event);
        })

打印event,结果是一个对象:
在这里插入图片描述
我们把event称作事件对象。其中,event可以看作是形参,可以任意更改名字。
这里简单定义一下事件对象:事件对象是事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击的信息,键盘。事件对象存在的前提是事件存在,由系统自动为我们创建

3.2 事件对象常用的属性和方法

3.2.1 阻止默认行为

非常常用!默认行为比如:链接跳转,按钮自动提交等等,我们可以通过事件对象阻止默认行为,下面以阻止链接跳转为例:

e.preventDefault()
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
            // e.preventDefault();//方法
            // e.returnValue;//属性
            return false;//通用,但不能执行后续代码
        })

3.2.2 阻止事件冒泡

事件冒泡是子到父,当我们为子与父都绑定了点击出现模态框事件,如何取消?见如下代码:

 e.stopPropagation();
        var father = document.querySelector('.father');
        var son = document.querySelector('.son');
        father.addEventListener('click', function() {
            alert('我是father');
        })
        son.addEventListener('click', function(e) {
            alert('我是son');
            e.stopPropagation();
        })

即可成功阻止

3.2.3 鼠标事件对象

在这里插入图片描述
我们有了事件对象,便可通过事件对象获取鼠标的位置。具体如上图,大家也可以拿下面的代码进行实验:

        document.addEventListener('click', function(e) {
            console.log(e.clientX);
            console.log(e.clientY);

            console.log(e.pageX);
            console.log(e.pageY);

            console.log(e.screenX);
            console.log(e.screenY);
        })

四,事件委托

定义:事件委托(事件代理)。是JavaScript中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡

大家请自行编译如下代码:

    <ul>
        <li>子元素</li>
        <li>子元素</li>
        <li>子元素</li>
        <li>子元素</li>
        <li>子元素</li>
    </ul>

    <script>
        //给父节点添加监听器
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            alert('弹出');
            e.target.style.backgroundColor = 'pink';
        })
    </script>

效果:当我们点击每个子元素li时候,都会弹出模块框‘弹出’。原因:
在这里插入图片描述
点击子元素后,由于是冒泡阶段(默认false),所以遍历顺序:子元素->父元素->document。所以,点击子元素后,会触发父元素,于是就会触发模块狂的弹出。

注意:使用“事件委托”时,并不是说把事件委托给的元素越靠近顶层就越好。事件冒泡的过程也需要耗时,越靠近顶层,事件的”事件传播链”越长,也就越耗时。如果DOM嵌套结构很深,事件冒泡通过大量祖先元素会导致性能损失。

后记

本节我们对事件流,事件对象,事件委托等内容进行了讲解。后续会更新更多底层原理及应用,谢谢喜欢,欢迎关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值