事件冒泡与事件捕获
浅谈事件冒泡和事件捕获
事件流
JS事件流最早要从IE和网景的浏览器大战说起,IE提出冒泡流,网景提出捕获流。后来在W3C统一下,js支持了捕获流和冒泡流,但是低版本的如IE6,IE7,IE8只支持冒泡流,所以为了浏览器兼容,还是建议使用冒泡流。
JS事件流的主要过程
首先来看一段代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<style>
.box{
width:500px;
height:500px;
border:1px solid #ff0;
}
.box01,.box02{
width:100px;
height:100px;
margin:100px 0 0 200px;
}
.box01{
border:1px solid #f0f;
}
.box02{
border:1px solid #0ff;
}
</style>
</head>
<body>
<div class="box">
<div class="box01"></div>
<div class="box02"></div>
</div>
</body>
<script>
$('.box').click(function(){
console.log("box")
})
$('.box01').click(function(){
console.log("box01")
})
$('.box02').click(function(){
console.log("box02")
})
</script>
</html>
将代码运行一下,点击类名为box01或box02的div,查看控制台即可得出子元素div的点击先触发,父级元素div的点击事件再触发。这个跟事件触发顺序有关。(图片转载侵删)
由上图可知,
1.一个完整的JS事件流是从window开始,最后回到window的一个过程。
2.事件流被分为三个阶段(1-5)捕获过程、(5-6)目标过程、(6-10)冒泡过程。
3.在冒泡过程中6比7早触发,也就解释了上面那题,为什么box01和box02,会比box先触发。
关于事件冒泡和事件捕获
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件。相反的,事件冒泡是自下而上的去触发事件。绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获。true,事件捕获;false,事件冒泡。默认false,即事件冒泡。Jquery的e.stopPropagation会阻止冒泡。
举个例子
先举一个例子,上html结构
<div id="outer">
<div id=inner" class="inner"></div>
</div>
接着给它们绑上事件
document.getElementById("outer").addEventListener("click",function(e){
alert("outer事件被触发,"+this.id);
})
document.getElementById("inner").addEventListener("click",function(e){
alert("inner事件被触发,"+this.id)
})
结果
inner事件被触发,inner
outer事件被触发,outer
结论:先inner,然后outer。事件的触发顺序自内向外,这就是事件冒泡.
改变一下参数
现在我们给它改变一下参数
document.getElementById("outer").addEventListener("click",function(e){
alert("outer事件被触发,"+e.target.id);
},true)
document.getElementById("inner").addEventListener("click",function(e){
alert("child事件被触发,"+e.target.id)
},true)
结果
outer事件被触发,outer
inner事件被触发,inner
结论:先outer,然后inner。事件的触发顺序自外向内,这就是事件捕获.
举个实例
貌似还是说的不太清,现在举个实例
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
</ul>
我们的需求是,鼠标移到li身上,对应li变色
我们可以给每个li绑上事件,比如…
$("li").on("mouseover",function(){
$(this).css("background-color","#cecece").siblings().css("background-color","white");
})
也可以利用事件冒泡来实现
$("ul").on("mouseover",function(e){
$(e.target).css("background-color","#cecece").siblings().css("background-color","white");
})
从简洁的程度上,两者差不多,但是事件冒泡明显比前面少了个遍历的过程,代码明显更优,而且如果ul再添加li子节点的话,新增的li一样会有点击事件的,这样下来,用事件冒泡来写的话更是方便了不少,这就涉及到了事件委托。