1、addEventListener的参数 有三个参数:第一个参数表示事件名称(不包括on,比如“click”);第二个参数表示要接收事件处理的函数,第三个参数为useCapture

记录一下第三个参数,有两种方式,可以设置成Boolean类型(useCapture)或者Object类型(options)

当第三个参数时Object类型时,

  • options包括三个布尔值选项:

  1、capture:默认false,是否使用时间捕获,也就是使用事件冒泡;

  2、once:默认值为false,是否只调用一次,如果是true,会在调用后自动销毁listener;

  3、passive:如果是true,意味着listener永远不会调用preventDefault方法,如果又确实调用了的话,

  浏览器只会console一个warning,而不会真的去执行preventDefault方法。根据规定默认值是false,

  但是chrome,FireFox等浏览器为了保证滚动时的性能,在document-level nodes(Window,

  Document,Document.body)上针对touchstart和touchmove事件,将passive默认值改为了true,

  保证了在页面滚动时不会因为自定义事件调用了preventDefault而阻塞页面渲染。

  • useCapture:默认值为false(即,使用事件冒泡)
    当第三个参数时Boolean类型的值,事件(event)在事件目标(eventTarget)中的顺序当DOM元素之间存在包含关系时,发生在元素上的事件有两种顺序。
  • Capturing  捕获
  • Bubbling   冒泡

Capturing就是从上往下

1                | |
2 ---------------| |-----------------
3 | element1     | |                |
4 |   -----------| |-----------     |
5 |   |element2  \ /          |     |
6 |   -------------------------     |
7 |        Event CAPTURING          |
8 -----------------------------------

这种情况下,事件发生后,注册在element1上的handler(事件)会先触发,注册在element2上的handler会后触发。

Bubbling就是从下往上:

1                / \
2 ---------------| |-----------------
3 | element1     | |                |
4 |   -----------| |-----------     |
5 |   |element2  | |          |     |
6 |   -------------------------     |
7 |        Event BUBBLING           |
8 -----------------------------------

这种情况下,事件发生后,注册在element2上的handler会先触发,注册在element1上的handler会后触发。

W3C标准中的事件顺序

1                  | |  / \
2 -----------------| |--| |-----------------
3 | element1       | |  | |                |
4 |   -------------| |--| |-----------     |
5 |   |element2    \ /  | |          |     |
6 |   --------------------------------     |
7 |        W3C event model                 |
8 ------------------------------------------

在W3C模型中,事件会先从上往下,到事件目标元素后,再从下往上,一直到最外面的元素。

代码示例

1 <div id="parent">parent div
2     <div id="child">child div</div>
3 </div>
1 const parent = document.querySelector('#parent');
 2 const child = document.querySelector('#child');
 3 
 4 function first() {
 5     alert('first');
 6 }
 7 function second() {
 8     alert('second');
 9 }
10 
11 parent.addEventListener('click', second, false);
12 child.addEventListener('click', first);

点击child元素,会先弹出first,然后弹出second。为什么会有这样呢?

click事件再child元素发生之后,第一步是capturing阶段,先从上往下寻找child元素的锚定元素中是否有可以触发的handler,如果useCapture是true的话就会再此阶段触发,结果发现没有可触发的handler。

click事件到达child元素后触发first方法,然后开始bubbling阶段,到达parent元素时发现有用于此阶段的handler,触发second方法。

如果把代码改成下面的样子

1 parent.addEventListener('click', second, true);
2 child.addEventListener('click', first);

点击child元素,会先弹出second,然后弹出first。分析过程如下:

click事件再child元素发生后,第一步是capturing阶段,先从上往下寻找child元素的锚定元素(Ancestor Element)中是否有可以触发的handler,发现可以触发second。

click事件到达child元素后触发first方法,然后开始bubbling阶段,到达parent元素时发现有用于此阶段的handler,没有发现可以触发的handler。

为了避免出现内存泄漏问题,可以用removeEventlister来清除掉eventListener。

js中阻止冒泡事件和默认事件的方法如下:

stopPropagation也是事件对象(Event)的一个方法,作用是阻止目标元素的冒泡事件,但是不会组织默认行为。
那么,什么是冒泡事件呢?

如在一个按钮上绑定click事件,那么click事件会一次在它的父级元素中被触发。stopPropagation就是阻止目标元素的事件冒泡到腹肌元素。

1 <div id='div' onclick='alert("div");'>
2 <ul onclick='alert("ul");'>
3 <li onclick='alert("li");'>test</li>
4 </ul>
5 </div>

我们单击test时,会依次触发alert(“li”),alert(“ul”),alert(“div”),这就是事件冒泡。

阻止冒泡

window.event? window.event.cancelBubble = true : e.stopPropagation();

取消默认事件

w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;

preventDefault是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。既然说是默认行为,当然是元素必须有默认行为才能被取消,如果元素本身就没有默认行为,调用当然无效。什么元素有默认行为呢?

如链<a>,提交按钮<input type="submit">等。当Event对象的cancelable为false时,表示没有默认行为,这时即使有默认行为,调用preventDefault也是不会起作用的。

我们都知道,链接<a> 的默认动作时跳转到指定页面,下面就以它为例,阻止它的跳转:

1 假如有链接<a href="http://caibaojian.com/" id="testA" >caibaojian.com</a>
2 var a = document.getElementById("testA");
3 a.onclick =function(e){
4 if(e.preventDefault){
5 e.preventDefault();
6 }else{
7 window.event.returnValue == false;
8 }
9 }

JavaScript的return false只会阻止默认行为,而用jQuery的话,既可以阻止默认行为,又可以防止事件冒泡。

下面是使用原生js,只会阻止默认行为,不会阻止冒泡

1 <div id='div'  onclick='alert("div");'>
 2     <ul  onclick='alert("ul");'>
 3         <li id='ul-a' onclick='alert("li");'><a         
 4         href="http://caibaojian.com/"id="testB">caibaojian.com</a> 
 5          </li>
 6     </ul>
 7 </div>
 8 var a = document.getElementById("testB");
 9 a.onclick = function(){
10 return false;
11 };

羡慕是使用jQuery,既阻止默认行为又停止冒泡。

1 <div id='div'  onclick='alert("div");'>
2     <ul  onclick='alert("ul");'>
3     <li id='ul-a' onclick='alert("li");'><a h    ref="http://caibaojian.com/"id="testC">caibaojian.com</a></li>
4     </ul>
5 </div>
6 $("#testC").on('click',function(){
7 return false;
8 });

总结使用方法

当需要停止冒泡行为时,可以使用 stopPropagation,IE浏览器可以使用cancelBubble =  true

1 function stopBubble(e) { 
2 //如果提供了事件对象,则这是一个非IE浏览器 
3 if ( e && e.stopPropagation ) 
4     //因此它支持W3C的stopPropagation()方法 
5     e.stopPropagation(); 
6 else 
7     //否则,我们需要使用IE的方式来取消事件冒泡 
8     window.event.cancelBubble = true; 
9 }

当需要阻止默认行为时,可以使用preventDefault,IE浏览器可以使用returnValue=false

1 //阻止浏览器的默认行为 
 2 function stopDefault( e ) { 
 3     //阻止默认浏览器动作(W3C) 
 4     if ( e && e.preventDefault ) 
 5         e.preventDefault(); 
 6     //IE中阻止函数器默认动作的方式 
 7     else 
 8         window.event.returnValue = false; 
 9     return false; 
10 }

 

 


w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true

关于JavaScript捕获和冒泡移步这位大佬的文章:

JavaScript捕获和冒泡探讨  http://caibaojian.com/javascript-capture-bubble.html