理解js事件冒泡事件委托事件捕获
js事件冒泡
javascript的事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止,这就是事件冒泡现象。
<div id="col">
<p>
<a id="btn" href="#">button</a>
</p>
</div>
<script>
let btnclick = document.getElementById('col');
btnclick.onclick=function(e){
console.log('1');
};
<script>
执行结果,当点击a标签时,也可以在控制台输出1;但是a元素并没有绑定click事件,这就是由于事件冒泡的现象,事件逐级传播给先辈元素,点击a——p——div,然后就可以执行对应的div绑定的事件。
特别说明:并不是所有的事件都有冒泡现象,比如如下几个:blur事件 focus事件 load事件
js事件委托
事件委托又可以叫事件代理,事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
事件委托的益处:我们都知道,减少dom操作可以提高网页性能,当一个页面的父级元素和很多子级元素都需要操作同一件事件的时候,我们不可能每个元素都去给它绑定一个事件,看下面例子:
<ul id="getNum"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> </ul> <script> let ptclick = document.getElementById('getNum'); let lilist = ptclick.querySelectorAll('li'); for(let i=0;i<lilist.length;i++){ lilist[i].index = i; }; ptclick.onclick = function(e){ var e = e || window.event; var target = e.target || e.srcElement; console.log(e.target.index); }; </script>
点击每个li元素都会打印对应的目标li的index值;
但是并不是所有的情况都适用于事件冒泡的,当出现父子级之间的注册事件不一致时,就不适用。关于事件委托更加详细的解释,查https://www.cnblogs.com/liugang-vip/p/5616484.html
每个例子都很详细的分析了。
js事件捕获
事件捕获恰好与事件冒泡相反,它从顶层祖先元素开始,直到事件触发元素。
DOM标准同时支持捕获事件模型和冒泡事件模型,但是,捕获事件模型先发生。两种事件流都会触发DOM中的所有对象,从document对象开始,也在document对象结束。
js事件捕获一般通过DOM2事件模型addEventListener来实现的:
target.addEventListener(type, listener, useCapture)
第三个参数默认设置为false,表示在冒泡阶段出发事件,设置为true时表示在捕获阶段触发,一般我们工作中似乎很少使用事件捕获。但还是要理解一下,面试过程中没少问过这类问题。
分析例子:
<div id="box"> <div id="middle"> <div id="inner"></div> </div> </div> <script> //事件捕获 window.onload=function(){ let box=document.getElementById("box"); let middle=document.getElementById("middle"); let inner=document.getElementById("inner"); box.addEventListener("click",function(){console.log("box")},true); middle.addEventListener("click",function(){console.log("middle")},true); inner.addEventListener("click",function(){console.log("inner")},true); } </script>
当点击inner绑定事件时,控制台会直接输出,box,middle,inner
js阻止事件冒泡
平时开发过程中,会用到大量的事件冒泡事件,但是可能我们在某个子级标签不需要传递事件给父级,这时候就需要阻止它事件的冒泡。
一般,使用stopPropagation来阻止事件的冒泡,IE中使用cancleBuble=true,stopPropagation也是事件对象(Event)的一个方法,作用是阻止目标元素的冒泡事件,但是会不阻止默认行为。
接上面事件冒泡的例子:
//阻止事件冒泡 let btna = document.getElementById('btn'); btna.onclick=function(e){ window.event? window.event.cancelBubble = true : e.stopPropagation(); };
此时,当点击a标签元素时,控制台就不会再打印出1;
阻止浏览器默认行为
开发过程中,总会出现各种浏览器的默认行为,这时候就需要阻止浏览器的默认行为,一般情况下,使用
preventDefault阻止浏览器的默认行为,在IE浏览器下,使用returnValue = false;
javascript的return false只会阻止默认行为,而是用jQuery的话则既阻止默认行为又防止对象冒泡。
//阻止浏览器的默认行为 function stopDefault( e ) { //一般情况下 if ( e && e.preventDefault ) e.preventDefault(); //IE中 else window.event.returnValue = false; return false; }