1. 程式人生 > >js事件流 事件捕獲 及時間冒泡詳解

js事件流 事件捕獲 及時間冒泡詳解

Javascript與HTML之間的互動是通過事件實現。

一、事件流

事件,是文件或瀏覽器視窗中發生的一些特定的互動瞬間。事件流,描述的是頁面中接受事件的順序。IE9,chrome,Firefox,Opera,Safari均實現了DOM2級規範中定義的標準DOM事件,而IE8和IE8以下版本仍然保留專有的事件處理方式。

事件冒泡

事件冒泡是由IE開發團隊提出來的,即事件開始時由最具體的元素(文件中巢狀層次最深的那個節點)接收,然後逐級向上傳播。

複製程式碼
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #myDiv{
            width:100px;
            height:100px;
            background-color:#FF0000;
        }
    </style>
    <body>
        <div id="myDiv"></div>
    </body>    
</html>
複製程式碼

 

當用戶點選了<div>元素,click事件將按照<div>—><body>—><html>—>document的順序進行傳播。若在<div>和<body>上都定義了click事件,如下:

複製程式碼
<script type="text/javascript">
        var div=document.getElementById("myDiv");
        div.onclick=function(event){
            alert("div");
        };
        document.body.onclick=function(event){
            alert("body");
        };    
</script>
複製程式碼

點選<div>,將先輸出“div”,再輸出“body”。

IE9,chrome,Firefox,Opera,Safari都支援事件冒泡,並將事件冒泡到window物件。

事件捕獲

事件捕獲是由Netscape Communicator團隊提出來的,是先由最上一級的節點先接收事件,然後向下傳播到具體的節點。當用戶點選了<div>元素,採用事件捕獲,則click事件將按照document—><html>—><body>—><div>的順序進行傳播。

若在<div>和<body>上都定義了click事件,如下:

複製程式碼
<script type="text/javascript">
        var div=document.getElementById("myDiv");    
        div.addEventListener("click",function(event){
            alert("div");
        },true);
        document.body.addEventListener("click",function(event){
            alert("body");
        },true);
        
    </script>
複製程式碼

(注:addEventListener具體使用見本文DOM2級事件處理)

點選<div>,將先輸出“body”,再輸出“div”。

IE9,chrome,Firefox,Opera,Safari都支援事件捕獲,但是IE8和IE8以下的版本只支援事件冒泡。儘管DOM2規範要求事件應該從document物件開始傳播,但是現在的瀏覽器實現都是從window物件開始捕獲事件。

DOM事件流

"DOM2級事件”規定的事件流包含三個階段:事件捕獲階段,處於目標階段和事件冒泡階段。首先發生的是事件捕獲,然後是實際的目標接收到事件,最後階段是冒泡階段。以上面的HTML頁面為例,單擊<div>元素將按照下圖觸發事件:

若在<div>和<body>上都定義了click事件,如下:

複製程式碼
<script type="text/javascript">
        var div=document.getElementById("myDiv");    
        div.onclick=function(event){
            alert("div");
        };
        document.body.addEventListener("click",function(event){
            alert("event bubble");
        },false);
        document.body.addEventListener("click",function(event){
            alert("event catch");
        },true);
        
    </script>
複製程式碼

點選<div>,將先輸出“event catch”,再輸出“div”,最後輸出“event bubble”。

二、事件處理程式

事件是使用者或瀏覽器自身執行的某種動作,而響應某個事件的函式叫做事件處理程式。HTML事件處理程式、DOM0級事件處理程式和IE事件處理程式均以“on”開頭,DOM2級事件處理程式不需要加“on”。

HTML事件處理程式

通過將事件作為HTML元素的屬性來實現,包含以下兩種方法:

1 < input  type="button" value="confirm" onclick="alert('confirm')" />

或者呼叫其他地方定義的指令碼:

<script type="text/javascript">
        function showMessage() {
            alert("confirm");
        }
</script>
<input type="button" value="confirm" onclick="showMessage()"/>

(注:函式定義必須放在呼叫之前)

DOM0級事件處理程式

 通過Javascript指定事件處理程式的傳統方式,所有瀏覽器均支援。每個元素(包括window,document)都有自己的事件處理程式屬性,但是必須在DOM節點載入完之後才會有效。如下所示:

<script type="text/javascript">
        var div = document.getElementById("myDiv");
        div.onclick = function(event) {
            alert("div");
        };
    </script>

使用DOM0級方法指定的事件處理程式被認為是元素的方法,在元素的作用域中執行。this引用當前元素,如下:

<script type="text/javascript">
        var div = document.getElementById("myDiv");
        div.onclick = function(event) {
            alert(this.id);
        };
    </script>

輸出“myDiv”。

刪除通過DOM0級方法指定的事件處理程式:div.onclick=null;

DOM2級事件處理程式

IE9,chrome,Firefox,Opera,Safari均實現了DOM2級事件處理程式,繫結事件方法addEventListener()接收三個引數:事件名稱,事件處理函式和一個布林值。布林值為true,則表示在捕獲階段呼叫事件處理程式;如果為false,則表示在冒泡階段呼叫事件處理程式。addEventListener允許在同一個元素上新增多個事件處理程式,如下所示:

複製程式碼
    <script type="text/javascript">
        var div = document.getElementById("myDiv");
        div.addEventListener("click", function(event) {
            alert("event bubble");
        }, false);
        div.addEventListener("click", function(event) {
            alert("event catch");
        }, true);
    </script>
複製程式碼

先輸出“event bubble”,後輸出“event catch”,說明addEvenListener繫結的處理程式執行順序和繫結順序相同。

通過DOM2級事件處理程式指定的方法,this也引用當前元素,如下:

<script type="text/javascript">
        var div = document.getElementById("myDiv");
        div.addEventListener("click", function(event) {
            alert(this.id);
        }, false);
    </script>

輸出“myDiv”。

刪除DOM2級事件處理程式,採用removeEventListener(),刪除時傳入的引數必須和繫結時傳入的引數相同,不能傳入匿名函式。如下所示:

複製程式碼
<script type="text/javascript">
        var div = document.getElementById("myDiv");
        var handler=function(event){
            alert("delete");
        };        
        div.addEventListener("click",handler,false);
        div.removeEventListener("click",handler,false);
    </script>
複製程式碼

IE事件處理程式

IE8和IE8以下的版本不支援addEventListener(),而是採用attachEvent()來實現事件繫結。目前只有IE和Opera支援attachEvent()。IE9支援addEventListener(),同時也相容IE8的attachEvent()方法,但是IE9和IE8對attachEvent()的實現有點不同。如下所示:

複製程式碼
    <script type="text/javascript">
        var div = document.getElementById("myDiv");
        div.attachEvent("onclick", function(event) {
            alert("1");
        });
        div.attachEvent("onclick", function(event) {
            alert("2");
        });
    </script>
複製程式碼

IE9和IE10先輸出“1”,再輸出“2”,而IE8和IE7先輸出“2”,再輸出“1”。

刪除IE事件處理程式,採用detachEvent(),刪除時傳入的引數必須和繫結時傳入的引數相同,不能傳入匿名函式。如下所示:

複製程式碼
<script type="text/javascript">
        var div = document.getElementById("myDiv");
        var handler = function(event) {
            alert("delete");
        };
        div.attachEvent("onclick",handler);
        div.detachEvent("onclick",handler);
    </script>
複製程式碼

總結:attachEvent()採用冒泡方式,而addEventListener()可以採用冒泡或事件捕獲方式。

先按由上往下的順序執行事件捕獲的執行程式,再執行目標元素的執行程式,最後按由下往上的順序執行冒泡事件。程式碼如下所示:

複製程式碼
<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>Event Bubbling Example</title>
    </head>
    <style type="text/css">
        #child {
            width: 100px;
            height: 100px;
            background-color: #FF0000;
        }
    </style>
    <body>
        <div id="parent">
            <div id="child"></div>
        </div>
    </body>
    <script type="text/javascript">
        var parent = document.getElementById("parent");
        var child = document.getElementById("child");
        child.onclick = function(event) {
            alert("child");
        };
        document.body.addEventListener("click", function(event) {
            alert("body:event bubble");
        }, false);
        parent.attachEvent("onclick", function(event) {
            alert("parent:event bubble");
        });
        document.body.addEventListener("click", function(event) {
            alert("body:event catch");
        }, true);
        parent.addEventListener("click", function(event) {
            alert("parent:event catch");
        }, true);
    </script>
</html>
複製程式碼

輸出順序:body:event catch—>parent:event catch—>child—>parent:event bubble—>body:event bubble

 

 

摘自:https://www.cnblogs.com/linxuehan/p/3623760.html