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