事件及事件流

事件與事件流

用戶在點擊網頁上某一按鈕時,瀏覽器會想辦法接收這一操做,如何接收呢? 瀏覽器會爲點擊操做劃定若干個範圍,從小到大依次是按鈕自己,包含這個按鈕的元素, 最後就是整個頁面。這一操做稱爲事件,而接收事件的次序稱爲事件流。 事件流總共有兩種形式:事件冒泡事件捕獲javascript

事件冒泡

事件冒泡就是從小到大,從具體對象到不具體對象,像泡泡同樣逐級向上html

<html></html>
<body>
    <div id="div1">
        <div id="div2">
            <button>click me!</button>
        </div>
    </div>
</body>

當用戶打開上述代碼編寫的頁面,點擊按鈕時,若是瀏覽器採起的是事件冒泡的事件接收機制, 那麼瀏覽器就先從button元素開始接收,而後是而後是div2,而後是div1,最終到document對象(規範是到document爲止, 可是大多數瀏覽器都會一直冒泡到window對象),如圖所示。java

事件捕獲

事件捕獲就是事件冒泡的反序。從大到小,從不具體對象到具體對象,逐級向下。瀏覽器

若是瀏覽器採起的是事件捕獲的事件接收機制, 瀏覽器先從document對象(規範定的是document對象,大多數瀏覽器是從window對象處開始接收)開始接收, 而後是<html>元素,而後是<body>元素,最後在<button>元素處接收。ui

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="contentType" content="text/html" />
        <title>Test</title>
    </head>
    <body>
        <div id="div1">
            <div id="div2">
                <button>click me!</button>
            </div>
        </div>
        <script src="scripts/test.js" type="text/javascript"></script>
    </body>
</html>

 

var div1 = document.querySelector("#div1");
var div2 = document.querySelector("#div2");
var button = document.querySelector("button");

div1.addEventListener("click",function(event){
    console.log("div1");
},false); //傳入false,事件冒泡
div2.addEventListener("click",function(event){
    console.log("div2");
},false);
button.addEventListener("click",function(event){
    console.log("button");
},false);

上述代碼使用addEventListener()方法,分別爲div1,div2,button元素添加了事件處理程序, 並顯示的指定事件流爲事件冒泡機制,瀏覽器按具體對象到不具體對象的順序接收事件。因此控制檯輸出spa

 

同一段代碼,但顯示的指定事件流爲事件捕獲機制,瀏覽器按不具體對象到具體對象的順序接收事件, 控制檯輸出。設計

有什麼用

理解事件流的這兩種機制有什麼用?其實這對理解某些DOM事件是頗有好處的,好比mouseover、mouseout、mouseleave、mouseenter。 其中,mouseover和mouseout是一對兒,鼠標進入目標元素時接收mouseover,離開目標元素時接收mouseout事件。 mouseenter和mouseleave是一對兒,鼠標進入目標元素時接收mouseenter,離開目標元素時接收mouseleave事件, 可是他倆不冒泡!因此鼠標進入、離開其後代元素時,其父元素沒法接受到mouseenter和mouseleave事件。code

 

<div id="target">
            <p>
                Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
            </p>
            <p>
                Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
            </p>
            <p>
                Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
            </p>
            <p>
                Lorem Ipsum is simply dummy text of the printing and typesetting industry.<br/>
                Lorem Ipsum has been the industry's standard dummy text ever since the 1500.
            </p>
        </div>
var target = document.querySelector("#target");
/**
 * 使用mouseenter和mouseleave事件,進入target時瀏覽器接受mouseenter事件,
 * 離開target時瀏覽器接受mouseleave事件。
 * 在target中移動鼠標(在各個<p>元素之間切換),由於不冒泡,因此target不會繼續接收到mouseenter和mouseleave,
 * 也就不會調用相應的事件處理程序
 */
target.addEventListener("mouseenter",function(event) {
    console.log("parent mouseenter");
},false);
target.addEventListener("mouseleave",function(event) {
    console.log("parent mouseleave");
},false);
/** * 使用mouseout和mouseover事件, 在target中移動鼠標(在各個<p>元素之間切換),因爲事件流是事件冒泡機制, * 因此target就會接收到其子元素冒泡而來的mouseenter和mouseleave,從而調用相應的事件處理機制 */ target.addEventListener("mouseout",function(event) { console.log("parent mouseout"); },false); target.addEventListener("mouseover",function(event) { console.log("parent mouseover"); },false);

如控制帶輸出所示,鼠標橫穿target,mouseenter僅觸發了一次,mouseleave也僅觸發了一次。而mouseout、mouseover觸發了若干次。htm

總結

事件:用戶的某一操做對象

事件流:瀏覽器接受事件的順序

事件冒泡:從具體對象到不具體對象,逐級向上接收

事件捕獲:從不具體對象到具體對象,逐級向下接收

 參考資料

1.《javascript高級程序設計》

相關文章
相關標籤/搜索