事件概述
JS与HTML之间的交互是通过事件实现的。事件,就是文档或浏览器窗口发生的一些特定的交互瞬间。可以使用监听器(事件处理程序)来预定事件,以便事件发生时执行相应的代码。事件是在IE3和Netscape Navigator2中出现的,当时是作为分担服务器运算负载的一种手段。
事件流
当一个HTML元素发生一个事件时,该事件会在目标节点与根节点(document)之间的路径传播,路径所经过的节点都会收到该事件,这个传播过程被称为DOM事件流。
DOM同时支持二种事件模型:捕获型事件和冒泡型事件。在DOM事件流模型中,捕获型事件先发生。两种事件流会触发DOM中的所有对象,从document对象开始,也在document对象结束。
二种事件流
冒泡事件流
冒泡事件流是由IE提出的,即事件最开始由目标节点接收,然后逐级向上传播到document根节点。
<style type="text/css">
#fa {width: 300px;height: 300px;background-color: red;}
#son {height:100px;width: 100px;background-color: green;}
</style>
<div id="fa">
<div id="son"></div>
</div>
<script type="text/javascript">
var fa = document.getElementById("fa");
var son = document.getElementById("son");
son.onclick = function() {
console.log("son 冒泡");
}
fa.onclick = function() {
console.log("fa 冒泡");
}
document.body.onclick = function(e) {
console.log("body 冒泡");
}
document.onclick = function() {
console.log("document 冒泡");
}
window.onclick = function() {
console.log("window 冒泡");
}
</script>
当点击id为son这个元素时,该单击事件会从son这个目标元素沿着DOM树逐级向上传播,直到代表浏览器的window对象。在这个事件传播的过程中只要该路径所经过的节点绑定了单击事件处理程序,事件传播到该节点时,该事件就会被触发。下面是JS脚本的执行结果。
捕获事件流
捕获事件流是由Netscape提出的。即事件从DOM树的根节点开始,逐级向下传播到目标节点。事件到达目标节点后,它会接着通过DOM节点再向上冒泡。
<style type="text/css">
.fa {height: 400px;width: 400px;background-color: red;}
.fa .son {height: 200px;width: 200px;background-color: green;}
</style>
<div class="fa">
<div class="son"></div>
</div>
<script type="text/javascript">
var ofa = document.querySelector("[class='fa']");
var oSon = document.querySelector("[class='son']");
window.addEventListener("click",function(e) {
console.log("window 捕获");
},true);
document.addEventListener("click",function(e) {
console.log("document 捕获");
},true);
document.body.addEventListener("click",function(e) {
console.log("body 捕获");
},true)
ofa.addEventListener("click",function(e) {
console.log("fa 捕获");
},true)
oSon.addEventListener("click",function(e) {
console.log("son 捕获");
},true)
</script>
当点击son这个目标元素时,事件最开始从window对象开始处理,然后逐级向下传播,直到目标元素。在传播的路径上,只要绑定了单击事件的节点,该节点的事件处理程序就会被执行。执行结果如下:
DOM事件流模型
"DOM2级事件"规定的事件流包括三个阶段:
- 捕获阶段:事件从Doucument节点自上而下向目标节点传播的阶段
- 目标阶段:真正的目标节点正在处理事件的阶段
- 冒泡阶段:事件从目标节点自下而上向Document节点传播的阶段。
IE8及更早版本不支持DOM事件流;IE9、Opera、Firefox、Chrome和Safari都支持DOM事件流。
<div id="fa">
<div id="son"></div>
</div>
<script type="text/javascript">
var fa = document.getElementById("fa");
var son = document.getElementById("son");
window.addEventListener("click",function() {
console.log("window捕获阶段");
},true);
document.addEventListener("click",function() {
console.log("document捕获阶段");
},true);
document.documentElement.addEventListener("click",function() {
console.log("HTML文档元素捕获阶段");
},true);
document.body.addEventListener("click",function() {
console.log("body捕获阶段");
},true);
fa.addEventListener("click",function() {
console.log("fa捕获阶段");
},true);
son.addEventListener("click",function() {
console.log("son捕获阶段");
},true);
window.addEventListener("click",function() {
console.log("window冒泡");
},false);
document.addEventListener("click",function() {
console.log("document冒泡");
},false);
document.documentElement.addEventListener("click",function() {
console.log("HTML文档元素冒泡");
},false);
document.body.addEventListener("click",function() {
console.log("body冒泡");
},false);
fa.addEventListener("click",function() {
console.log("fa冒泡");
},false);
son.addEventListener("click",function() {
console.log("son冒泡");
},false);
</script>
点击id为son的元素将会打印出下面的结果: