本博文源于js基础,今天学习js的事件流。事件流可以让我们对整个h5+c3有个“心中有丘壑”的把握。本博文包含以下内容
事件流
事件流
js有规定,两个div嵌套,内层div放置一个按钮,点击这个按钮之后,不仅触发了这个按钮的点击事件,而且也触发了两个div的点击事件,甚至也触发了body和window的点击事件。
其中,最外层的元素和最内层的元素谁先触发事件。js规定了一个事件的传播方向,称为事件流。 事件流依次有两个阶段:事件捕获阶段、事件冒泡阶段。
冒泡阶段和捕获阶段
- 事件捕获阶段:从外层元素往内层传播。
- 事件冒泡阶段:从内层元素往外层传播。
例子:测试事件流响应
案例效果
从上往下按钮的事件依次被执行
附上代码
<body>
<div id="box1">
<div id="box2">
<button id="btn">按我</button>
</div>
</div>
<script type="text/javascript">
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var btn = document.getElementById("btn");
btn.onclick = function() {
alert("按钮被点击");
}
box1.onclick = function() {
alert("box1被点击");
}
box2.onclick = function() {
alert("box2被点击");
}
</script>
</body>
DOM0级事件监听
何谓0级事件监听,其实它就是一种标准。我们日常用oDiv.onclick = function()添加事件监听,它就是一种DOM0级事件监听。
事件处理函数执行顺序是从最内层依次到最外层的。事件按这个方向传播:按照上面的例子,先是最内层的按钮,然后是box2,接下来是box1、body、document和window对象。事件处理函数的书写顺序和触发的先后没有任何关系。
DOM0级事件的局限性是它只能从内到外监听到事件的冒泡阶段,无法监听捕获阶段的点击事件还有一个特点是支持覆盖。
例如:
box1.onclick = function() {alert("我弹不出来");};
box1.onclick = function() {alert("弹出我,我把上面的覆盖了");};
//最后执行第二条语句
DOM2级事件监听
在DOM2标准中,新增加了addEventListener()函数,称为DOM2级事件监听。它可以灵活地设置监听的阶段。
函数中有3个参数,格式如下:
- 第1个参数是事件名,这里的事件名不能写on前缀
- 第2个参数是事件处理函数,即事件发生时做的事情
- 第3个参数时布尔值,true表示监听捕获阶段,false表示监听冒泡阶段
DOM2级的事件监听中,如果给同一个元素的同一个事件名的同一个阶段添加多个事件监听,彼此不覆盖,谁先写就先执行谁。
例子:监听按钮被点击的捕获和冒泡阶段
实验效果
简而言之:从外向内捕获,从内向外冒泡。
对于最内层按钮来说,谁先写就先执行谁,不分捕获和冒泡。
附上代码
<body>
<div id="box1">
<div id="box2">
<button id="btn">按我</button>
</div>
</div>
<script type="text/javascript">
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var btn = document.getElementById("btn");
box1.addEventListener("click",function() {
alert("我是box1的捕获阶段");
},true);
box1.addEventListener("click",function() {
alert("我是box1的冒泡阶段");
},false);
box2.addEventListener("click",function() {
alert("我是box2的捕获阶段");
},true);
box2.addEventListener("click",function() {
alert("我是box2的冒泡阶段");
},false);
btn.addEventListener("click",function() {
alert("我是btn的捕获阶段");
},true);
btn.addEventListener("click",function() {
alert("我是btn的冒泡阶段");
},false);
</script>
</body>
事件监听的移除
有时需要移除元素的事件监听,例如拖拽效果。
0级事件监听的移除很简单,直接把onclick属性设置为null即可:
oBox.onclick = null;
此时oBox对象就没有onclick事件监听了。
2级事件监听移除的时候,必须“指名道姓”去移除。也就是说, 语法:
box.removeEventListener("click",boxClickHandler,true);
如果是匿名函数添加的事件监听,是不可能去掉的。
事件对象
事件对象概述
任何事件处理函数,系统都会自动向其传入一个event参数,封装这次事件的一些细节,如鼠标点击的位置等。
例子:通过div将event进行输出
测试效果
附上代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
#box {
width: 200px;
height:200px;
background-color: orange;
}
</style>
</head>
<body>
<div id="box"></div>
<script type="text/javascript">
var box = document.getElementById("box");
box.onclick = function(event) {
console.log(event);
}
</script>
</body>
</html>
event.target属性
事件处理对象event对象一定有一个target属性,它表示事件阶段的最早来源。其含义是,若监听的是冒泡阶段,则event.target就是最内层元素,因为最内层元素就冒泡阶段的来源;而如果监听捕获阶段,则event.target是最外层元素,因为最外层元素就是捕获阶段的来源。
例子:利用按钮将event.target属性打印出来
测试效果
折用了0级别事件,因此输出按钮。
实验代码
<body>
<div id="box1">
<div id="box2">
<button id="btn">按我</button>
</div>
</div>
<script type="text/javascript">
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var btn = document.getElementById("btn");
box1.onclick = function(event) {
console.log(event.target);
}
</script>
</body>
阻止事件继续传播
事件流分为两个阶段,在捕获阶段,事件从最外层盒子传到最内层;在冒泡阶段,事件从最内层传到最外层。
可以使用event.stopPropagation()来阻止事件继续传播.event对象是任何事件处理函数中的事件对象。
例子:用函数方法阻止单击继续弹盒子
在页面上制作3个盒子嵌套结构,分别是外层盒子box1、中层盒子box2、内层盒子box3,分别监听它们的捕获阶段的点击事件。
如果点击最内层盒子,按照正常情况先弹出“A”,然后“B”,然后“C”。但是在box2里做了事件阻塞,就不会弹出“C”框了。这就是阻止事件继续传播的妙用。
测试效果
附上代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
.box1 {
width:300px;
height: 300px;
padding: 50px;
background-color: skyblue;
}
.box2{
width:160px;
height:160px;
padding:70px;
background-color: purple;
}
.box3{
width:55px;
height:55px;
padding:50px;
background-color: orange;
}
</style>
</head>
<body>
<div class="box1" id="box1">
<div class="box2" id="box2">
<div class="box3" id="box3"></div>
</div>
</div>
<script type="text/javascript">
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
var box3 = document.getElementById("box3");
box1.addEventListener("click",function(){
alert("A");
},true);
box2.addEventListener("click",function(){
event.stopPropagation();
alert("B");
},true);
box3.addEventListener("click",function(){
alert("C");
},true);
</script>
</body>
</html>