1.事件流javascript
事件流:从页面中接收事件的顺序。也就是说当一个事件产生时,这个事件的传播过程,就是事件流。css
IE中的事件流叫事件冒泡;事件冒泡:事件开始时由最具体的元素接收,而后逐级向上传播到较为不具体的节点(文档)。对于html来讲,就是当一个元素产生了一个事件,它会把这个事件传递给它的父元素,父元素接收到了以后,还要继续传递给它的上一级元素,就这样一直传播到document对象(亲测如今的浏览器到window对象,只有IE8及下不这样);html
再多说一句,如今的浏览器默认是采用的是事件冒泡;在DOM0级方法绑定事件只能是事件冒泡,不能设置;在DOM2级你能够设置是用事件冒泡仍是事件捕获(下面说);java
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
<style type="text/css">
#child{background: red;width: 50px;height: 50px;}
#father{width: 100px;height: 100px;background: green;}
#grandparent{
width: 150px;height: 150px;background: black;margin: 100px auto 0;}
</style>
</head>
<body>
<div id="grandparent">
<div id="father">
<div id="child"></div>
</div>
</div>
</body>
<script type="text/javascript">
var grandparent=document.getElementById("grandparent");
var parent=document.getElementById("father");
var child=document.getElementById('child');
var body=document.body;
var html=document.getElementsByTagName("html")[0];
child.onclick=function(){
console.log("我是儿子");
}
parent.onclick=function(){
console.log("我是父亲");
}
grandparent.onclick=function(){
console.log("我是爷爷");
}
window.onclick=function(){
console.log("我是window");
}
document.onclick=function(){
console.log("我是document");
}
html.onclick=function(){
console.log("我是html");
}
body.onclick=function(){
console.log("我是body");
}
</script>chrome
</html>浏览器
当我点击红色部分函数
会打印这样:测试
我测试了(PS:我用的都是最新版的)chrome,firefox,opera,IE11,IE10,IE9都是这个结果,也就是说如今都冒泡到window对象,不只仅是到document对象,可是IE8及以前的就冒泡到document就结束了;this
这就是事件冒泡,它会把你这个click事件,一级一级的向上传递,若是相应的元素也绑定click事件处理程序(这里强调是click事件,若是你是给绑定了其它事件,那没用),那么它的这个事件处理程序也会执行,也就产生了上面的结果了;spa
形象的就是跟水里的鱼吐泡泡似的,慢慢的向上传递;
事件捕获是网景(Netscape)提出来的,事件捕获是不太具体的元素应该更早接受到事件,而最具体的节点应该最后接收到事件。他们的用意是在事件到达目标以前就捕获它;也就是跟冒泡的过程正好相反,以html的click事件为例,document对象(DOM级规范要求从document开始传播,可是如今的浏览器是从window对象开始的)最早接收到click事件的而后事件沿着DOM树依次向下传播,一直传播到事件的实际目标;我测试了一下(我用的都是最新的浏览器),chrome,opera,firefox,IE11到IE9都支持事件捕获。
代码等着我在下面讲DOM事件流再一块说明;
DOM2级中规定了事件流要包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。这是W3C采用了他们两家的事件监听机制。(说点题外话,w3c中的不少标准就是这样,浏览器厂商有不少本身的私有解决问题方式,好用的就被W3c采纳了)DOM2级还规定,实际发生事件的元素在捕获阶段不能接收到事件。咱们就以上面的事件冒泡时的代码说明这个过程:按照标准是这样的,当一个元素产生了事件,事件是从document到html再到body再到DIV爷爷再到DIV爸爸,这时候捕获阶段就应该中止了,再进入下一个阶段“处于目标阶段”,而后是从DIV爸爸到DIV爷爷再到body再到html再到document,这就是事件冒泡阶段;实际上咱们把处于目标阶段即第二阶段看做是冒泡阶段的一部分,即冒泡的开始;其实是怎么样的呢?先上代码,仍是前面的代码只是改了一下js代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
<style type="text/css">
#child{ background: red; width:50px; height:50px; }
#father{ width:100px; height:100px; background:green; }
#grandparent{ width:150px; height:150px; background:black; margin:100px auto 0; }
</style>
</head>
<body>
<div id="grandparent">
<div id="father">
<div id="child"></div></div>
</div>
</body>
<script type="text/javascript">
var grandparent = document.getElementById("grandparent");
var parent = document.getElementById("father");
var child = document.getElementById('child');
var html = document.getElementsByTagName("html")[0];
var body = document.body;
grandparent.addEventListener("click",function ()
{console.log("I am capturing grandparent"); },true);
grandparent.addEventListener("click",function () {console.log("I am grandparent"); },false);
parent.addEventListener("click",function() {console.log("I am parent"); },false);
parent.addEventListener("click",function() { console.log("I am capturing parent"); },true);
child.addEventListener("click",function() { console.log("I am capturing child"); },true);
child.addEventListener("click",function() { console.log("I am child"); },false);
body.addEventListener("click",function() { console.log("I am body"); },false);
body.addEventListener("click",function() { console.log("I am capturing body"); },true);
html.addEventListener("click",function() { console.log("I am capturing html"); },true);
html.addEventListener("click",function() { console.log("I am html"); },false);
document.addEventListener("click",function() { console.log("I am capturing document"); },true);
document.addEventListener("click",function() { console.log("I am document"); },false);
window.addEventListener("click",function() {console.log("I am window"); },false);
window.addEventListener("click",function() {console.log("I am capturing window"); },true);
</script></html>
代码有点多见谅了!也是为了最能说明问题!
打印是这样的:
这是我点击最里面DIV儿子元素所发生的情形,能够看出捕获阶段也能触发目标元素上的事件,而不只仅是在冒泡阶段;而且仍是从window开始,到最后再以window对象结束,浏览器厂商就是任性,不把W3c看在眼里。你的标准我想实现就实现不想就不实现;
当我把DIV爷爷的事件绑定方式换成DOM0级的方式,其余的保持不变,即
grandparent.onclick = function() { console.log("我是在哪一个阶段发生呢?") }
是这样打印的
再次说明了我上面在IE事件流中强调的,用DOM0级绑定事件时,事件只发生冒泡的阶段;