1. 程式人生 > >js之事件冒泡和事件捕獲詳細介紹

js之事件冒泡和事件捕獲詳細介紹

1-1 ppr lang strong 傳播 默認 ont 也不會 element

(1)冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發。

IE 5.5: div -> body -> document

IE 6.0: div -> body -> html -> document

Mozilla 1.0: div -> body -> html -> document -> window

(2)捕獲型事件(event capturing):事件從最不精確的對象(document 對象)開始觸發,然後到最精確(也可以在窗口級別捕獲事件,不過必須由開發人員特別指定)。

(3)DOM事件流:同時支持兩種事件模型:捕獲型事件和冒泡型事件,但是,捕獲型事件先發生。兩種事件流會觸及DOM中的所有對象,從document對象開始,也在document對象結束。

DOM事件模型最獨特的性質是,文本節點也觸發事件(在IE中不會)。

支持W3C標準的瀏覽器在添加事件時用addEventListener(event,fn,useCapture)方法,基中第3個參數 useCapture是一個Boolean值,用來設置事件是在事件捕獲時執行,還是事件冒泡時執行。而不兼容W3C的瀏覽器(IE)用 attachEvent()方法,此方法沒有相關設置,不過IE的事件模型默認是在事件冒泡時執行的,也就是在useCapture等於false的時候 執行,所以把在處理事件時把useCapture設置為false是比較安全,也實現兼容瀏覽器的效果。

技術分享

事件捕獲階段:事件從最上一級標簽開始往下查找,直到捕獲到事件目標(target)。
事件冒泡階段:事件從事件目標(target)開始,往上冒泡直到頁面的最上一級標簽。

假設一個元素div,它有一個下級元素p。
<div>
  <p>元素</p>
</div>
這兩個元素都綁定了click事件,如果用戶點擊了p,它在div和p上都觸發了click事件,那這兩個事件處理程序哪個先執行呢?事件順序是什麽?

兩種模型
以前,Netscape和Microsoft是不同的實現方式。

Netscape中,div先觸發,這就叫做事件捕獲。

Microsoft中,p先觸發,這就叫做事件冒泡。

兩種事件處理順序剛好相反。IE只支持事件冒泡,Mozilla, Opera 7 和 Konqueror兩種都支持,舊版本的Opera‘s 和 iCab兩種都不支持 。

事件捕獲
當你使用事件捕獲時,父級元素先觸發,子級元素後觸發,即div先觸發,p後觸發。

事件冒泡
當你使用事件冒泡時,子級元素先觸發,父級元素後觸發,即p先觸發,div後觸發。

W3C模型
W3C模型是將兩者進行中和,在W3C模型中,任何事件發生時,先從頂層開始進行事件捕獲,直到事件觸發到達了事件源元素。然後,再從事件源往上進行事件冒泡,直到到達document。

程序員可以自己選擇綁定事件時采用事件捕獲還是事件冒泡,方法就是綁定事件時通過addEventListener函數,它有三個參數,第三個參數若是true,則表示采用事件捕獲,若是false,則表示采用事件冒泡。

ele.addEventListener(‘click‘,doSomething2,true)

true=捕獲

false=冒泡

傳統綁定事件方式
在一個支持W3C DOM的瀏覽器中,像這樣一般的綁定事件方式,是采用的事件冒泡方式。

ele.onclick = doSomething2

IE瀏覽器
如上面所說,IE只支持事件冒泡,不支持事件捕獲,它也不支持addEventListener函數,不會用第三個參數來表示是冒泡還是捕獲,它提供了另一個函數attachEvent。

ele.attachEvent("onclick", doSomething2);

附:事件冒泡(的過程):事件從發生的目標(event.srcElement||event.target)開始,沿著文檔逐層向上冒泡,到document為止。

事件的傳播是可以阻止的:
• 在W3c中,使用stopPropagation()方法
• 在IE下設置cancelBubble = true;
在捕獲的過程中stopPropagation();後,後面的冒泡過程也不會發生了~
3.阻止事件的默認行為,例如click <a>後的跳轉~
• 在W3c中,使用preventDefault()方法;
• 在IE下設置window.event.returnValue = false;
4.哇,終於寫完了,一邊測試一邊寫的額,不是所有的事件都能冒泡,例如:blur、focus、load、unload,(這個是從別人的文章裏摘過來的,我沒測試)。

例如:

  事件機制默認是從子向父,傳到某個元素的時候如果沒有指定是捕獲會采用冒泡。

(1)事件冒泡:(從子向父)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-1.8.3.js"></script>
    <script>
/*        $(document).click(function () {
            alert("document點擊!!!!");
        })*/
        $(function () {
//            window.preventDefault();
//            window.preventBubble();
//            window.stopPropagation();
            $("div").click(function () {
                alert("div點擊");
            });
          $("p").click(function () {
                alert("p被點擊");
            });
            $(document)[0].addEventListener(‘click‘,function () {
                alert("document點擊!!!!");
            },false)
        });

    </script>
</head>
<body>
<div>
    <p>p1</p>
    <p>p2</p>
</div>


</body>
</html>

  

結果:點擊P1的時候

技術分享

技術分享

技術分享

(2)事件捕獲:(從父向子)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="jquery-1.8.3.js"></script>
    <script>
        $(function () {
            $("p").click(function () {
                alert("p被點擊");
            });
            $(document)[0].addEventListener(‘click‘, function () {
                alert("document點擊!!!!");
            }, true)
            $("div")[0].addEventListener(‘click‘, function () {
                alert("div點擊!!!!");
            }, true)
        });

    </script>
</head>
<body>
<div>
    <p>p1</p>
    <p>p2</p>
</div>


</body>
</html>

結果:點擊P1的時候

技術分享

技術分享

技術分享

js之事件冒泡和事件捕獲詳細介紹