事件冒泡:当某个子标签的事件被触发后,执行完绑定该事件的函数后,会依次触发所有的父标签事件,一直传递到根标签,在这个标签嵌套关系链中,如果某个标签绑定了同名事件,则执行该事件,否则继续向上一级传递;也可以理解为这种比较粗暴的说法:事件冒泡顾名思义就是往外冒,从里到外依次触发绑定的同名事件函数。 事件捕获:当用户触发某个标签后,会从根标签开始逐层向子标签寻找该事件的标签。延续粗暴的风格,事件捕获就是从外到里。 直接上例子吧:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style> *{ margin:0; padding:0; } #box{ width:500px; height:500px; background:red; } #div1{ width:300px; height: 300px; background:skyblue; } #div2{ width:100px; height:100px; background:orange; } </style> <script> window.onload = function(){ var box = document.querySelector('#box'); var div1 = document.querySelector('#div1'); var div2 = document.querySelector('#div2'); div2.onclick = function(){ alert('我是橙色盒子'); } div1.onclick = function(){ alert('我是蓝色盒子'); } box.onclick = function(){ alert('我是红色盒子'); } } </script> </head> <body> <div id="box"> <div id="div1"> <div id="div2"></div> </div> </div> </body> </html>跑完这段代码,点击橙色盒子之后,会看到这种景象,依次弹出三个弹窗,分别是我是橙色盒子,我是蓝色盒子,我是红色盒子。 其实我们本意只是想要看到显示 ‘’我是橙色盒子‘’的弹窗,为什么会接连触发另外两个盒子呢,这就是事件冒泡搞的鬼,那该如何解决这种问题呢?
解决方案一:stopPropagation( )阻止事件冒泡
<script> window.onload = function(){ var box = document.querySelector('#box'); var div1 = document.querySelector('#div1'); var div2 = document.querySelector('#div2'); div2.onclick = function(ev){ var e = event || ev; e.stopPropagation(); alert('我是橙色盒子'); } div1.onclick = function(ev){ var e = window.event || ev; e.stopPropagation(); alert('我是蓝色盒子'); } box.onclick = function(ev){ var e = window.event || ev; e.stopPropagation(); alert('我是红色盒子'); } } </script>再次执行之后,你会发现我们在点击橙色盒子的时候,其他事件不会继续冒泡了。 解决方案二 : cancelBubble = true;
<script> window.onload = function(){ var box = document.querySelector('#box'); var div1 = document.querySelector('#div1'); var div2 = document.querySelector('#div2'); div2.onclick = function(ev){ var e = event || ev; e.cancelBubble = true; alert('我是橙色盒子'); } div1.onclick = function(ev){ var e = window.event || ev; e.cancelBubble = true; alert('我是蓝色盒子'); } box.onclick = function(ev){ var e = window.event || ev; e.cancelBubble = true; alert('我是红色盒子'); } } </script>也能达到同样效果。 事实上stopPropagation和cancelBubble的作用是一样的,都是用来阻止浏览器默认的事件冒泡行为。
两种方法作用都是一样的,都是阻止事件冒泡行为,区别在于cancelBubble 是为了兼容IE浏览器,stopPropagation是为了供谷歌、火狐等浏览器使用,两者可以结合使用。
看到这里,你可能有些疑惑,事件冒泡感觉还是没什么卵用啊 我们设想一下这个场景: 我们需要让鼠标滑过li标签显示某些内容,如果给每一个li标签都添加事件是不是有些消耗性能。如果我给ul添加事件,是不是不用遍历li标签了,这样做提高了代码执行效率。