事件委托原理及应用(必学知识点总结)

  • 事件委托原理及应用(必学知识点总结)已关闭评论
  • 13 次浏览
  • A+
所属分类:Web前端
摘要

事件流:用于描述页面接收事件的顺序。以下是事件流的两种不同方案:事件冒泡:事件由最具体的元素逐级向上传递到最不具体的元素。

事件委托与事件对象


事件冒泡与事件捕获

事件流:用于描述页面接收事件的顺序。以下是事件流的两种不同方案:

事件冒泡:事件由最具体的元素逐级向上传递到最不具体的元素

事件捕获:事件由最不具体的元素逐级向下传递到最具体的元素

以上的两种事件流方案是截然相反的,分别由IE开发团队和Netscape开发团队提出。


添加事件处理的方法

HTML事件处理程序:利用特定HTML标签的事件属性(<input>)。代码如下:

<input type="button" value="测试" onclick="test()"> <script> let test = () => { // 利用标签属性添加事件     console.log('已被点击') } </script> 

DOM0事件处理程序:利用DOM节点自带的事件属性。代码如下:

<input type="button" value="测试" id="test"> <script> let test = document.querySelector('#test') test.onclick = () => { // 利用onlick属性添加事件     console.log('已被点击') } </script> 

DOM2事件处理程序(推荐):利用DOM节点(继承自EventTarget)的添加事件监听器方法。代码如下:

<input type="button" value="测试" id="test"> <script> let test = document.querySelector('#test') test.addEventListener('click', ()=>{ // 利用添加事件监听器方法     console.log('已被点击') }) </script> 

说明:在网页DOM编程中的继承关系:EventTarget <= Node <= Element。因此上面的test变量拥有addEventListener方法


DOM2 Events事件流

事件委托原理及应用(必学知识点总结)

捕获阶段Document => Element html => Element body => Element div

冒泡阶段Element div => Element body => Element html => Document

我们首先了解EventTarget.addEventListener(type, listener, options)这个方法的一些内部参数:

type:监听事件的类型

listener:接收一个回调函数,事件触发后会执行。

options:里面有比较多的可选项参数,这里我们利用capture(布尔值:默认为false)这个参数。表示监听的事件在捕获阶段会触发listener执行。

接下来我们利用上面的方法还原上面DOM2事件流的捕获阶段与冒泡阶段,如下:

<div style="cursor: pointer">我是一个事件,请点击验证</div> <script> // 捕获阶段 document.addEventListener("click", () => {     console.log("捕获阶段1:Document") // document }, true) document.documentElement.addEventListener("click", () => {     console.log("捕获阶段2:Element html") // html }, true) document.body.addEventListener("click", () => {     console.log("捕获阶段3:Element body") // body }, true) document.querySelector("div").addEventListener("click", () => {     console.log("捕获阶段4:Element div") // div }, true) // 冒泡阶段 document.querySelector("div").addEventListener("click", () => {     console.log("冒泡阶段4:Element div") // div }, false) document.body.addEventListener("click", () => {     console.log("冒泡阶段5:Element body") // body }, false) document.documentElement.addEventListener("click", () => {     console.log("冒泡阶段6:Element html") // html }, false) document.addEventListener("click", () => {     console.log("冒泡阶段7:Document") // document }, false) </script> 
事件委托原理及应用(必学知识点总结)

很明显,上面的代码验证了网页的事件触发会存在DOM2事件流这一执行过程。我们点击了事件,这个事件经历了由捕获阶段再到冒泡阶段的传递。


事件对象常用属性和方法

方法属性 说明
Event.target 只读 对事件原始目标的引用。
Event.type 只读 事件的类型,不区分大小写。
event.preventDefault 取消默认事件(如果该事件可取消)。
event.stopPropagation 停止冒泡,阻止事件在 DOM 中继续冒泡。

其中Event.target最为常用,具体指代触发了相应事件的Node节点目标。


事件委托的应用(实现hover悬停变色效果)

需求:实现一个列表,鼠标进入或离开都会使列表子元素的背景颜色改变。

如果没有事件委托,我们一般实现这个需求应该这样做。如下:

<div class="list" style="height: 400px; width: 400px;">     <ul style="list-style: none; text-align: center;">         <li>1</li>         <li>2</li>         <li>3</li>         <li>4</li>     </ul> </div> <script> let list = document.querySelectorAll('.list > ul > li'); // 遍历DOM集合,给每个li添加事件 list.forEach(element => {     element.addEventListener('mouseover', () => {         element.style.backgroundColor = 'green';     })     element.addEventListener('mouseout', () => {         element.style.backgroundColor = '';     }) }); </script> 

我们遍历每个li元素并为其添加鼠标移入与移出事件。目前总共添加了八个事件处理程序。

注意:在JavaScript中,事件处理程序的数量会影响页面的整体性能。

因此对上述实现方式我们有必要采取措施优化。利用事件委托优化如下:

// 点击li元素后会通过事件冒泡机制触发ul添加的click事件。 <div class="list" style="height: 400px; width: 400px;">     <ul style="list-style: none; text-align: center;">         <li>1</li>         <li>2</li>         <li>3</li>         <li>4</li>     </ul> </div> <script> let list = document.querySelector('.list > ul'); // 直接给ul父元素添加事件即可 list.addEventListener('mouseover', (event) => {     if (event.target.nodeName.toLowerCase() === 'li') {         event.target.style.backgroundColor = 'green';     } }) list.addEventListener('mouseout', (event) => {     if (event.target.nodeName.toLowerCase() === 'li') {         event.target.style.backgroundColor = '';     } }) </script> 

我们只给list元素添加了两个事件,同样实现了需求。如果采用原始方式,我们一共给这些li元素添加了八个事件。利用事件委托的方式进行网页性能的优化,其效果不言而喻。


参考

MDN-Event

JavaScript高级程序设计(第4版)