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級綁定事件時,事件只發生冒泡的階段;