浅谈js事件冒泡和事件捕获
程序员文章站
2022-06-28 10:47:12
前言:最近正好在找工作,当面试官问到我事件冒泡和事件捕获的时候,我想我的回答并不全面合理,基于这方面的原因,我打算抽点时间来和大伙聊聊, 并不一定全面,多多包涵。 首先咱们先聊聊事件冒泡: 什么是事件冒泡 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发 元素->父元 ......
前言:最近正好在找工作,当面试官问到我事件冒泡和事件捕获的时候,我想我的回答并不全面合理,基于这方面的原因,我打算抽点时间来和大伙聊聊,
并不一定全面,多多包涵。
首先咱们先聊聊事件冒泡:
什么是事件冒泡
- 事件冒泡:如果一个元素的事件被触发,那么他的所有父级元素的同名事件也会被依次触发
- 元素->父元素->body->html->document->window
- 事件冒泡一直存在,只不过以前我们没有给父级元素加同名事件
<!doctype html> <html> <head lang="en"> <meta charset="utf-8"> <title></title> <style> #box{ width: 300px; height: 300px; background-color: hotpink; position: relative; } #son{ width: 100px; height: 100px; position: absolute; left: 350px; top: 350px; background-color: yellowgreen; } </style> </head> <body> <div id="box"> <input type="button" value="点我" id="btn"/> <div id="son"></div> </div> </body> </html> <script> window.onclick = function () { alert("window被点击了"); } document.onclick = function () { alert("文档被点击了"); } document.documentelement.onclick = function () { alert("html被点击了"); } document.body.onclick = function () { alert("body被点击了"); } document.getelementbyid("box").onclick = function () { alert("我是骚粉的大盒子"); }; document.getelementbyid("btn").onclick = function () { alert("我是小按钮"); }; document.getelementbyid("son").onclick = function () { alert("我是又黄又绿的小盒子"); }; </script>
事件冒泡的好处
- 事件冒泡好处:如果想给父元素的多个子元素添加事件,我们可以只需要给父元素添加事件即可,然后
- 通过获取事件源(e.target)就可以得知是哪一个子元素触发了这个事件
<!doctype html> <html> <head lang="en"> <meta charset="utf-8"> <title></title> </head> <body> <ul id="ul1"> <li>隔壁老王1</li> <li>隔壁老王2</li> <li>隔壁老王3</li> <li>隔壁老王4</li> <li>隔壁老王5</li> </ul> </body> </html> <script> var ul = document.getelementbyid("ul1"); //1.如果想给ul中的每一个li标签添加点击事件,以前的做法需要遍历ul的li标签逐个添加 // for (var i = 0; i < ul.children.length; i++) { // // ul.children[i].onclick = function () { // // alert(this.innerhtml); // } // } //2.使用时间冒泡:只需要给父元素添加点击事件即可 ul.onclick = function (e) { e = e || window.event; var target = e.target || e.srcelement; console.log(target.innerhtml); //target:事件源:触发本次事件的源头 alert(e.target.innerhtml); } </script>
事件冒泡的影响
- 事件冒泡会导致需求冲突:例如我想要添加一个功能,弹出登录窗之后点击body空白区域让登陆窗消失
- 此时a标签弹出登录窗的点击事件会触发body的点击事件,导致登陆窗一出来就消失
阻止事件冒泡
- 阻止事件冒泡:让同名事件不要在父元素中冒泡(触发)
* 说人话:点击一个元素只会触发当前元素的事件,不会触发父元素的同名事件
- 语法: 事件对象.stoppropagation() ie8及之前不支持
- 事件对象.cancelbubble = true ie8之前支持
- 注意:如果想要阻止事件冒泡,一定要在触发事件的函数中接收事件对象
事件捕获
- 1.事件冒泡:从触发事件元素,一级一级往上找父元素触发同名事件,如果有就触发
- 2.事件捕获:从最*的父元素一级一级往下找子元素触发同名事件,直到触发事件的元素为止
- 事件捕获与事件冒泡触发事件的顺序完全相反
- 3.事件捕获,只能通过addeventlistener并且参数写true才是事件捕获
- 其他都是冒泡(不是通过addeventlistener添加、addeventlistener参数为false)
- 4.事件对象.stoppropagation() 除了可以阻止冒泡还可以阻止捕获
- 5.ie8及以前没有捕获!
<!doctype html> <html> <head lang="en"> <meta charset="utf-8"> <title></title> <style> #box { width: 300px; height: 300px; background-color: hotpink; position: relative; } #son { width: 100px; height: 100px; position: absolute; left: 350px; top: 350px; background-color: yellowgreen; } </style> </head> <body> <div id="box"> <div id="son"></div> </div> </body> </html> <script>
var box = document.getelementbyid("box"); var son = document.getelementbyid("son"); window.addeventlistener("click", function () { alert("这是window"); },true) document.addeventlistener("click", function () { alert("这是document"); },true) document.documentelement.addeventlistener("click", function (e) { e = e || window.event; alert("这是html"); e.stoppropagation();//阻止事件冒泡和事件捕获 },true) document.body.addeventlistener("click", function () { alert("这是body"); },true) //参数3:默认是false,代表是支持事件冒泡 box.addeventlistener("click", function () { alert("这是box"); },true) son.addeventlistener("click", function () { alert("这是son"); },true) </script>
事件的三个阶段
- 1.事件一共有三个阶段:事件的执行顺序
- 1--捕获阶段 :
- 2--目标阶段 :
- 3--冒泡阶段 :
- 2.事件对象.eventphase 可以获得触发这个事件时,到底是哪个阶段
- 3.先从最*往下一级一级捕获,然后到目标的捕获,目标的冒泡,再一级一级往上冒泡
<!doctype html> <html> <head lang="en"> <meta charset="utf-8"> <title>标题</title> <style> .one { width: 200px; height: 200px; background-color: pink; } .son { width: 100px; height: 100px; background-color: green; position: absolute; left: 250px; top: 250px; } </style> </head> <body> <div class="one" id="box"> <input type="button" value="按钮" id="btn"/> <div class="son" id="son"></div> </div> <script> var box = document.getelementbyid("box"); var btn = document.getelementbyid("btn"); var son = document.getelementbyid("son"); document.addeventlistener("click",function (e) { alert("document"+ e.eventphase); },true) ;//true表示事件捕获,所以是阶段1,并且优先执行 document.body.addeventlistener("click", function (e) { alert("哈哈,我是body"+ e.eventphase); },false); box.addeventlistener("click",function (e) { alert("哈哈哈,我是粉色的盒子box..."+ e.eventphase); },false); btn.addeventlistener("click",function (e) { alert("哈哈哈,我是按钮btn..."+ e.eventphase); },false); son.addeventlistener("click",function (e) { alert("嘻嘻嘻,我是绿色的盒子son"+ e.eventphase); },false); </script> </body> </html>