DOM事件流与事件委托

事件流

事件流描述的是从页面中接收事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流。

在这里插入图片描述
DOM事件流分为3个阶段

  • 捕获阶段
  • 当前目标阶段
  • 冒泡阶段

事件冒泡

IE最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到DOM最顶层节点的过程。

<div id="first">
  <div id="second">
    <div id="third"></div>
  </div>
</div>
#first {
  width: 200px;
  height: 200px;
  margin: 0 auto;
  background: red;
  border: 1px solid #ccc;
}
#second {
  width: 150px;
  height: 150px;
  margin: 24px auto;
  background: yellow;
  border: 1px solid #ccc;
}
#third {
  width: 100px;
  height: 100px;
  margin: 24px auto;
  background: blue;
  border: 1px solid #ccc;
}

addEventListener第三个参数是false那么则处于冒泡阶段,不写则默认为false

first.addEventListener('click', function () {
  console.log('红色');
});
second.addEventListener('click', function () {
  console.log('黄色');
});
third.addEventListener('click', function () {
  console.log('蓝色');
});

在这里插入图片描述

事件捕获

网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。

first.addEventListener('click', function () {
  console.log('红色');
},true);
second.addEventListener('click', function () {
  console.log('黄色');
},true);
third.addEventListener('click', function () {
  console.log('蓝色');
},true);

addEventListener第三个参数是true那么则处于捕获阶段。

在这里插入图片描述

事件在不同阶段执行

first.addEventListener('click', function () {
  console.log('红色');
});
second.addEventListener('click', function () {
  console.log('黄色');
},true);
third.addEventListener('click', function () {
  console.log('蓝色');
});

在这里插入图片描述
JavaScript代码中只能执行捕获或者冒泡其中的一个阶段,我们可以这么来理解:

  • 此处单击蓝色框后,事件捕获阶段
    从外向内捕获,到红色时,红色有事件,需在冒泡阶段执行,但此时是捕获阶段,先不执行,接下来是黄色,黄色在捕获阶段执行,所以先执行。
  • 到达当前目标阶段
    执行目标对象的事件函数,控制台输出蓝色。
  • 到达冒泡阶段
    由目标向外冒泡,到黄色时,捕获阶段已经执行,最后到达红色,红色在冒泡阶段执行,控制台输出红色。

实际开发中我们很少使用事件捕获,我们更关注事件冒泡。
其中onclickattachEvent只能得到冒泡阶段。
还有些事件是没有冒泡的,比如onbluronfocusonmouseenteronmouseleave

事件委托

假如,当我们需要给ul中的多个li添加点击事件时,通常会为每个li标签加上点击事件,此时看起来每个li的点击事件触发时调用的都是一个函数,但其实不是这样,每个li绑定的都是一个全新的函数,只不过样子一模一样,这里我们可以判断一下:

let liList = document.querySelectorAll('li')
for (let i = 0; i < liList.length; i++) {
  liList[i].onclick = function () {
    console.log(this.innerHTML)
  }
}
console.log(liList[0].onclick == liList[1].onclick); //false

至此,我们可以得到结论,有多少个li,那么就会有多少个函数被创建在内存中占据空间,这样对内存的开销是巨大的。

前面我们介绍到了事件冒泡的原理,那么我们就可以通过这种机制把事件加在父元素的身上,也就是ul标签,这样ul里面的li做点击事件时,都会冒泡到ul上,所以都会触发,这就是事件委托,委托它们的父级代为执行事件。

Event对象

  • 官方解释:event对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
  • 简单理解:事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法。

这个event是个形参,系统帮我们设定为事件对象,不需要传递实参过去。当我们注册事件时,event对象就会被系统自动创建,并依次传递给事件监听器(事件处理函数)。

event对象提供了一个属性叫target,可以返回事件的目标节点,我们称为事件源,也就是说,target就可以表示为当前的事件操作的dom,但不是真正操作dom

IE678兼容性解决:e=e||window.event
下面我们可以这样改写:

let ul = document.querySelector('ul')
ul.onclick = function (e) {
  e = e || window.event
  console.log(e.target.innerHTML)
}

这样如果li数量较多,就可以大大减少dom操作,优化的性能可想而知。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值