200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > JavaScript(js)事件冒泡 事件捕获 事件委托详解

JavaScript(js)事件冒泡 事件捕获 事件委托详解

时间:2023-06-23 20:15:19

相关推荐

JavaScript(js)事件冒泡 事件捕获 事件委托详解

JavaScript(js)事件冒泡、事件捕获、事件委托详解

1.什么是事件

JavaScript和HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口发生的一些特定的交互瞬间。可以使用监听器(或事件处理程序)来预定事件,以便事件发生时执行相应的代码。通俗的说,这种模型其实就是一个观察者模式。(事件是对象主题,而这一个个的监听器就是一个个观察者)

2.事件流

事件流描述的是从页面中接收事件的顺序。而IE和Netscape提出了完全相反的事件流概念。IE事件流是事件冒泡,而Netscape的事件流就是事件捕获。

3.事件冒泡

IE的事件流叫做事件冒泡。即事件开始时由最具体的元素(当前元素target,文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。所有现代浏览器都支持事件冒泡,并且会将事件一直冒泡到window对象。

4.事件捕获

事件捕获的思想是不太具体的节点(最外层dom节点)应该更早的接收到事件,而在最具体的节点(target节点)应该最后接收到事件。事件捕获的用以在于事件到达预定目标之前捕获它。IE9+、Safari、Chrome、Opera和Firefox支持,且从window开始捕获(尽管DOM2级事件规范要求从document)。由于老版本浏览器不支持,所以很少有人使用事件捕获。

5.DOM事件流

“DOM2级事件”规定事件流包括三个阶段,事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的事件捕获,为截获事件提供了机会。然后是实际的目标接收了事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。

6.示例

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JavaScript事件测试<style>#a{width: 300px;height: 300px;background: pink;}#b{width: 200px;height: 200px;background: blue;}#c{width: 100px;height: 100px;background: yellow;}</style></head><body><div id="a">a<div id="b">b<div id="c">c</div></div></div><script>window.onload=function(){var a = document.getElementById("a"),b = document.getElementById("b"),c = document.getElementById("c");c.addEventListener("click", function (event) {console.log("c1");// 注意第三个参数没有传进 false , 因为默认传进来的是 false//,代表冒泡阶段调用,个人认为处于目标阶段也会调用的});c.addEventListener("click", function (event) {console.log("c2");}, true);b.addEventListener("click", function (event) {console.log("b");}, true);a.addEventListener("click", function (event) {console.log("a1");}, true);a.addEventListener("click", function (event) {console.log("a2")});a.addEventListener("click", function (event) {console.log("a3");event.stopImmediatePropagation();}, true);a.addEventListener("click", function (event) {console.log("a4");}, true);}</script></body></html>

• 点击b或者c,控制台输出a1、a3

stopImmediatePropagation包含stopPropagation的功能,它会阻止同一事件的所有传播功能(捕获或者冒泡),stopPropagation只阻止同一事件对应的那个函数,同一事件的其他绑定函数不会阻止。由于stopImmediatePropagation阻止该元素上后来绑定的事件处理程序被调用以不输出 a4。因为事件捕获被拦截了,自然不会触发 b、c 上的事件,所以不输出 b、c1、c2,冒泡更谈不上了,所以不输出 a2。

• 点击c,控制台输出a1、a2、a3

点击c时,此时事件流是处于目标阶段,不是冒泡阶段、也不是捕获阶段,事件处理程序被调用的顺序是注册的顺序(代码的书写顺序)。不论你指定的是true还是false。换句话来说就是现在点击的是a这个盒子本身,它处于事件流的目标状态,而既非冒泡,又非捕获。(需要注意的是,此时的eventPhase为2,说明事件流处于目标阶段。当点击a的时候,先从document捕获,然后一步步往下找,找到a这个元素的时候,此时的target和currentTarget是一致的,所以认定到底了,不需要再捕获了,此时就按顺序执行已经预定的事件处理函数,执行完毕后再继续往上冒泡…)

• 事件流原则(实际测试过)

(1)从外向内,先是捕获阶段,在目标(target)阶段,最后是冒泡阶段

(2)非target节点元素,先捕获后冒泡

(3)Target节点元素,按代码书写顺序(事件的注册顺序)执行(无论是冒泡还是捕获)

7.事件委托

事件委托又叫时间代理,指的是利用事件的冒泡原理,只给外层的父容器添加监听事件,若子元素有点击事件,则会冒泡到父容器上,即子元素委托父元素代为执行事件。

• 事件委托的应用场景

例如,一个播放列表有成千上万首歌曲,如果遍历播放列表,给每个 item 添加点击事件,而这样无疑会多次访问 DOM,每次 DOM 操作都会引起浏览器的重绘与重排,非常不利于性能优化。

这时候我们可以利用事件委托,只给最外层的容器添加响应事件,这样只需一次 DOM 操作,就能达到目的。

<!DOCTYPE html><html><head><meta charset="utf-8"><title>事件委托测试例子()</title></head><body><ul id="music"><li>青花瓷</li><li>东风破</li><li>双节棍</li><li>追梦</li><li>破红尘</li><li>沙漠骆驼</li><li>我是一只小小鸟</li><li>探清水河</li><li>典狱司</li><li>江湖少年</li><li>狂浪生</li><li>盛世回收</li></ul><script>window.onload=function(){var $music = document.getElementById('music');$music.addEventListener('click', function(e) {if(e.target.nodeName.toLowerCase() === 'li') {// 判断目标元素target是否为li元素var content = e.target.innerHTML;console.log(content);}}, false)}</script></body></html>

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。