事件流
在第四代 Web 浏览器(IE4 和 Netscape Communicator 4)开始开发时,开发团队碰到了一个有意思的问题:页面哪个部分拥有特定的事件呢?要理解这个问题,可以在一张纸上画几个同心圆。把手指放到圆心上,则手指不仅是在一个圆圈里,而且是在所有的圆圈里。两家浏览器的开发团队都是以同样的方式看待浏览器事件的。当你点击一个按钮时,实际上不光点击了这个按钮,还点击了它的容器以及整个页面。
事件流描述了页面接收事件的顺序。结果非常有意思,IE 和 Netscape 开发团队提出了几乎完全相反的事件流方案。IE 将支持事件冒泡流,而 Netscape Communicator 将支持事件捕获流。
事件冒泡(IE事件流)
IE 事件流被称为事件冒泡,这是因为事件被定义为从最具体的元素(文档树中最深的节点)开始触发,然后向上传播至没有那么具体的元素(文档)。
面试官:什么是事件冒泡
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ color: white; font-size: 20px; } #outer{ width: 300px; height: 300px; background-color: red; } #center{ width: 200px; height: 200px; background-color: blue; } #inner{ width: 100px; height: 100px; background-color: green; } </style> </head> <body> <div id="outer">outer <div id="center">center <div id="inner">inner</div> </div> </div> <script> var inner = document.getElementById('inner'); var center = document.getElementById('center'); var outer = document.getElementById('outer'); // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样 inner.onclick = function () { console.log('我是inner点击的'); } // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象 center.onclick = function () { console.log('我是center点击的'); } outer.onclick = function () { console.log('我是outer点击的'); } </script> </body> </html>
效果:
点击inner之后会输出inner,和后面父级的center、outer
在点击页面中的id为inner的div元素,click事件会以如下顺序发生
由内向外
div#inner
div#center
div#outer
body
html
document
也就是说,div#inner元素,即被点击的元素,最先触发 click 事件。然后,click 事件沿DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象。
所有现代浏览器都支持事件冒泡,只是在实现方式上会有一些变化。IE5.5及早期版本会跳过html元素(从body直接到 document)。现代浏览器中的事件会一直冒泡到 window 对象。
阻止事件冒泡
使用阻止事件冒泡之前,先要知道DOM事件默认提供的一个对象,HTML DOM Event对象。
Event 对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
event.stopPropagation()
直接在对应方法中使用event.stopPropagation()便可阻止事件冒泡。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ color: white; font-size: 20px; } #outer{ width: 300px; height: 300px; background-color: red; } #center{ width: 200px; height: 200px; background-color: blue; } #inner{ width: 100px; height: 100px; background-color: green; } </style> </head> <body> <div id="outer">outer <div id="center">center <div id="inner">inner</div> </div> </div> <script> var inner = document.getElementById('inner'); var center = document.getElementById('center'); var outer = document.getElementById('outer'); // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样 inner.onclick = function (event) { console.log('我是inner点击的'); //阻止事件冒泡 event.stopPropagation(); } // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象 center.onclick = function () { console.log('我是center点击的'); } outer.onclick = function () { console.log('我是outer点击的'); } </script> </body> </html>
效果:
点击inner之后只会输出inner,而后面父级的不会输出center、outer了
注意:如果点击方法时需要同时传递其他参数和event,直接传递event这个单词即可
onclick="test(123,event)"
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ color: white; font-size: 20px; } #outer{ width: 300px; height: 300px; background-color: red; } #center{ width: 200px; height: 200px; background-color: blue; } #inner{ width: 100px; height: 100px; background-color: green; } </style> </head> <body> <div id="outer">outer <div id="center">center <!-- 第一种:匿名函数 ,整体性好--> <!-- <div id="inner" onclick="myFun(123,event)">inner</div> --> <!-- 第二种:有名函数 --> <div id="inner" onclick="myFun(123,event)">inner</div> </div> </div> <script> var inner = document.getElementById('inner'); var center = document.getElementById('center'); var outer = document.getElementById('outer'); /* // 当我们只有一个inner点击方法的时候 我们发现想要实现的效果和我们预期的一样 //第一种:匿名函数 inner.onclick = function (event) { console.log('我是inner点击的'); //阻止事件冒泡 event.stopPropagation(); } */ // 第二种:有名函数 var myFun=function(a,event){ console.log(a,event); } // 但是当我们给inner的父元素和祖先元素也添加点击事件时 一点击inner 所有祖先元素的事件都会被触发,这就是事件冒泡现象 center.onclick = function () { console.log('我是center点击的'); } outer.onclick = function () { console.log('我是outer点击的'); } </script> </body> </html>
效果: 点击inner之后只会输出inner,而后面父级的不会输出center、outer了
面试题7:Js事件流,事件冒泡(IE事件流)
于 2022-04-18 15:01:09 首次发布