事件委托的理解(事件委托原理及应用(必学知识点总结))
事件委托与事件对象
事件冒泡与事件捕获
事件流:用于描述页面接收事件的顺序 。以下是事件流的两种不同方案:
事件冒泡:事件由最具体的元素逐级向上传递到最不具体的元素 。
事件捕获:事件由最不具体的元素逐级向下传递到最具体的元素 。
以上的两种事件流方案是截然相反的 ,分别由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>我是一个事件 ,请点击验证</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"> <ul> <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"> <ul> <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版)
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!