1. 程式人生 > >JavaScript事件冒泡,事件捕獲,事件處理,事件委託

JavaScript事件冒泡,事件捕獲,事件處理,事件委託

早期的事件,是作為分擔伺服器運算負載的一種手段,實文件或者瀏覽器視窗中發生的一些特定的互動瞬間,如點選按鈕,拖放檔案等。我們可以使用偵聽器來預定事件,當事件釋出時候就可作出相應的響應,這種模式稱為觀察者模型。

事件流

事件流是從頁面接收事件的順序。在一個html頁面中,dom元素組成一顆dom樹,由於子元素一般所處的位置都會在父元素之中。那麼,當這個子元素被點選時候,可以認為子元素受到了點選,也可以認為父元素受到點選。那麼確定誰先接收這個點選事件就成了瀏覽器需要解決的問題。

事件冒泡

IE在處理上述事件時候,是由事件開始最具體的元素(文件中巢狀層次最深的那個節點)接收,然後逐級向上傳播到根節點。這就是事件冒泡。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <div id="container"></div>
</body>
</html>

在如上程式碼裡面,如果單擊了div元素,那麼接著<body>、<html>、document會按著順序收到點選事件。

事件捕獲

Netscape Communicator團隊提出了一種與IE完全相反的一種解決辦法,接收事件的順序為根節點到具體的節點,這種方法就是事件捕獲。也就是在上面的這個例子中,接收點選事件的順序為document、<html>、<body>、<div>。

DOM事件流

“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處於目標階段和事件冒泡階段。首先發生的是事件捕獲,然後處於目標階段,最後才事件冒泡。依然以上面的程式碼為例子,單擊div時,首先document獲得點選事件,依次到<html>、<body>,之後事件捕獲結束。事件捕獲的意義在於,能夠在目標獲得點選事件之前截獲事件,並對其作出相應的處理。處於目標階段時,div能夠執行繫結的事件處理程式,之後再到事件冒泡階段。即使“DOM2級事件”規範明確規定捕獲階段不會涉及事件目標,但是瀏覽器基本都會 實現在捕獲階段觸發事件物件上的事件,也就是說,可以在事件捕獲階段觸發事件物件的事件處理程式,這種情況通常都需要在繫結事件處理程式的情況下指明可在捕獲階段觸發。如果非必須,最好不要使用事件捕獲。

事件處理程式

HTML事件處理程式

dom元素一般都有支援事件的特性,例如onclick等,這個特性的值應該是能夠執行的JavaScript程式碼,這些JavaScript程式碼就是其事件處理程式,例如:
<input type="button" value="click me" onclick="alert('click')" />

也可以呼叫在頁面其他地方定義的指令碼:
<input type="button" value="click me" onclick="handler()">
<script>
    function handler() {
        alert('click');
    }
</script>

在HTML頁面中指定事件處理程式有三個缺點:存在時差,當指令碼較綁定了事件dom元素慢,那麼使用者在指令碼沒有加載出來的過程就觸發事件會導致報錯;另一個缺點是這樣擴充套件事件處理程式的作用域鏈在不同的瀏覽器會導致不同的結果,即this的指向不一致;最後,這種緊密耦合的程式碼風格導致維護的成本升高,在以後修改程式碼的時候需要修改HTML程式碼和js程式碼。

DOM0級事件處理程式

通過JavaScript指定事件處理程式的傳統方式,就是將一個函式賦值給一個事件處理程式屬性。這種指定事件處理程式具有簡單,跨瀏覽器的優點,其事件處理程式會在事件流的冒泡階段被觸發:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <input id="myButton" type="button" value="click me">
    <script>
        var button = document.getElementById('myButton');
        function handler() {
            alert('click');
        }
        button.onclick = handler;
        // 移除事件
        // button.onclick = null;
    </script>
</body>
</html>

注意,此種方式無法為同一個元素對同一事件指定多個事件處理程式,如果繫結多次,就會以最後一次為準。

DOM2級事件處理程式

DOM2級事件定義了兩個方法,用於處理指定和刪除事件處理程式的操作:addEventListener()和removeEventListener()。它們接受三個引數:處理的事件名稱,事件處理程式,一個指定是在事件冒泡還是事件捕獲階段處理的布林值,true則為在事件捕獲階段處理,false為在事件冒泡階段處理。需要注意的是,通過addEventListener()指定的事件處理程式智慧通過removeEventListener()移除;同時,如果在addEventListener()中的第二個引數是一個匿名函式,則無法通過removeEventListener()移除,也沒有辦法移除。而IE實現了與DOM中類似的兩個方法:attachEvent()和detachEvent(),這兩個方法直接收兩個引數,第一個為事件名稱(注意事件名稱都有on字首,例如click事件則為onclick),第二個引數為事件處理程式函式。以下示例是相容了瀏覽器的事件繫結函式:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <input id="myButton" type="button" value="click me">
    <script>
        function addHandler(element, type, handler) {
            if (element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + type, handler);
            } else {
                element['on' + type] = handler;
            }
        }

        function removeHandler(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.detachEvent) {
                element.detachEvent('on' + type, handler);
            } else {
                element['on' + type] = null;
            }
        }

        var button = document.getElementById('myButton');

        function handler() {
            alert('click');
        }

        addHandler(button, 'click', handler);
        // removeEventListener(button, 'click', handler);
    </script>
</body>
</html>

事件委託

事實上,作業系統給瀏覽器分配的資源會比其他桌面應用少,主要是怕黑客利用網頁應用進行大量的計算,導致計算機的資源被過多佔用而down機等其他原因。JavaScript影響網頁應用效能有很多方面,如:每個函式都是物件,都會佔用記憶體;記憶體中的物件越多,效能越差。其次,必須事先指定所有事件處理程式而導致的DOM訪問次數越多,就會造成越長的頁面互動就緒時間。所以多個事件處理程式過多就會降低事件的效能,解決這種問題的方案就是事件委託。事件委託利用事件冒泡,只指定一個事件處理程式,就可以管理某一類的所有事件。例如,可以在DOM樹中儘可能高的層次新增一個事件處理程式,之後就可以操作事件目標元素:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
    <ul id="myLinks">
        <li id="goSomewhere">Do something</li>
        <li id="doSomething">Do something</li>
        <li id="sayHi">Say Hi</li>
    </ul>
    <script>
        function addHandler(element, type, handler) {
            if (element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + type, handler);
            } else {
                element['on' + type] = handler;
            }
        }

        function removeHandler(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.detachEvent) {
                element.detachEvent('on' + type, handler);
            } else {
                element['on' + type] = null;
            }
        }

        var list = document.getElementById('myLinks');

        function handler(event) {
            event = event ? event : window.event;
            var target = event.target || event.srcElement;
            switch(target.id) {
                case 'doSomething':
                    alert('doSomething');
                    break;
                case 'goSomewhere':
                    alert('goSomewhere');
                    break;
                case 'sayHi':
                    alert('hi');
                    break;
            }
        }

        addHandler(list, 'click', handler);
        // removeEventListener(list, 'click', handler);
    </script>
</body>
</html>

由上面的程式碼可看出,只獲取了一個DOM元素,只添加了一個事件處理程式,所以能夠減少記憶體的使用。但是,不建議對mouseover和mouseout使用事件代理,因為當滑鼠從一個元素移到其子節點時,或者當滑鼠移除該元素時,都會觸發mouseout事件。

相關推薦

論UDX併發單臺伺服器1.5w聯接每條聯接傳送1KB資料10秒內沒處理斷開聯接--之改進過程

      對於併發這個話題已經討論很多,特別是在TCP大量聯接的成功案例很多。這裡不例舉,少說幾W多則上10W都有。      但是作為UDP可靠傳輸協議來說,每個事務處理都需要我們的CPU完成,而且我們要維護心跳,保證條條連線能正常收發,不讓洞給關掉了,使聯接斷開。所

機器學習:樸素貝葉斯分類器決策函式向量化處理mask使用技巧

文章目錄 前面實現的樸素貝葉斯分類器,決策函式是非向量化的: 藉助於numpy向量化處理,相當於平行計算,注意mask使用技巧,用途較廣: 前面實現的樸素貝葉斯分類器,決策函式是非向量化的: 前面提到過大資料處理,儘量避免個人的遍歷等一些函式

XStream實現xml和java物件之間的互相轉換(包括對屬性別名下劃線_的處理)同理JSON也可以

首先去官網下載響應JAR包 最少需要兩個jar包,一個xstream.jar,一個是xmlpull.jar 首先來看下java物件到xml的轉換 package xml; class PhoneNumber { private int code;

openstack建立虛擬機器流程從介面任務發起到nova等元件處理到虛機建立完成

1.客戶端使用自己的使用者名稱密碼請求認證。 2.keystone通過查詢在keystone的資料庫user表中儲存了user的相關資訊,包括password加密後的hash值,並返回一個token_id(令牌),和serviceCatalog(一些服務的endpoint地址,cinder、glance-ap

javascript事件監聽事件冒泡/捕獲總結

一、javascript事件監聽的三種方法 element.addEventListener(type, listener[, useCapture]); // IE6~8不支援 element.attachEvent('on' + type, listener); //

JavaScript事件冒泡事件捕獲事件處理事件委託

早期的事件,是作為分擔伺服器運算負載的一種手段,實文件或者瀏覽器視窗中發生的一些特定的互動瞬間,如點選按鈕,拖放檔案等。我們可以使用偵聽器來預定事件,當事件釋出時候就可作出相應的響應,這種模式稱為觀察者模型。 事件流 事件流是從頁面接收事件的順序。在一個html頁面中,

事件事件捕獲事件冒泡-基礎知識總結------彭記(018)

sca ie9 com pre 類型 har code 做出 viewport 事件流: -事件流包括三個階段-事件捕獲階段、處於目標階段和事件冒泡階段。 -首先發生的是事件捕獲,為截獲事件提供了機會,然後是實際的目標接收到事件,最後一個階段是冒泡階段,可以在這個階段對事件

關於事件事件冒泡事件捕獲

有意 clas 向上 接收 上傳 單擊事件 sca dom 描述 1.事件流 假設有這樣一個場景: 有一個導航條:div > ul > li > a,每個元素塊寬高一樣,就像是一組同心圓。如果我們點擊a元素,那麽瀏覽器會認為單擊事件不僅僅發生在a上。換

事件綁定事件捕獲事件冒泡以及事件委托兼容IE

window t對象 找到 添加多個 src 階段 之前 事件監聽 hang ● 事件分為三個階段: 事件捕獲 --> 事件目標 --> 事件冒泡 ● 事件捕獲:事件發生時(onclick,onmouseover……)首先發生在document上,然後依

事件冒泡事件捕獲事件委托

onclick .get function cli ren 技術分享 image html www <div id="parent" onclick="checkCookie()"> <div class="child" id="chil

js的事件冒泡事件捕獲

capture func fun == alt lis select tlist con addEventListener() 方法可以指定 "useCapture" 參數來設置傳遞事件類型:false→冒泡 true→捕獲 默認false。

js中的事件維託事件捕獲事件冒泡

事件維託:利用冒泡的原理把事件加到父元素或祖元素上,觸發執行效果。 事件冒泡(event bubbling):ie的事件流,從最具體的元素逐級向上傳播到較為具體的節點,如果你單擊了頁面中的<div>元素,那麼這個click事件會按照如下順序傳播。1<div>,2&l

js中的事件捕獲事件冒泡以及由事件冒泡引入的事件委託

事件模型 首先我們認識一下事件模型: 上圖轉自:https://zhuanlan.zhihu.com/p/26536815 由上圖所示,事件模型分為三個階段: 捕獲階段 目標階段 冒泡階段 在IE8及其以前,IE瀏覽器監聽事件的API為attac

js高階:enebt事件冒泡事件捕獲

1.事件   瀏覽器客戶端上客戶觸發的行為都稱為事件 所有的事件都是天生自帶的,不需要我們去繫結,只需要我們去觸發。 通過 obj.事件名=function(){} 事件名:onmouseover 滑鼠懸浮      onmouseout   滑鼠移除     onmousedown滑鼠

事件事件冒泡事件捕獲

1.事件 瀏覽器客戶端上客戶觸發的行為都稱為事件 所有的事件都是天生自帶的,不需要我們去繫結,只需要我們去觸發。 通過obj.事件名=function(){} 事件名:onmouseover onmouseout onmousedown onmousemove onmouseup Onclick&n

關於JS中事件捕獲事件冒泡事件代理(事件委託及e.target與e.currentcurrentTarget的區別

事件捕獲:        表示事件的觸發順序,當繫結事件方法的第三個引數值設定為true時,事件觸發的順序為捕獲。        當一個元素的事件被觸發的時候(如onclick事件),該事件會從document開

事件流(事件冒泡捕獲函式閉包等)

事件流 事件流描述的是從頁面中接受事件的順序,當幾個都具有事件的元素層疊在一起的時候,那麼你點選其中一個元素,並不是只有當前被點選的元素會觸發事件,而層疊在你點選範圍的所有元素都會觸發事件。 事件流包括兩種模式:冒泡和捕獲 事件捕獲: 父級元素先觸發,子集元素後觸發;(由外到

事件冒泡捕獲委託

冒泡,捕獲事件 IE使用的是事件冒泡,其他瀏覽器則是事件捕獲 他們是描述事件觸發時序問題的術語。事件捕獲指的是從document到觸發事件的那個節點,即自上而下的去觸發事件。相反的,事件冒泡是自下而上的去觸發事件。 繫結事件方法的第三個引數,就是控制事件觸發順序

冒泡捕獲事件繫結阻止事件冒泡阻止預設行為

Internet Explorer 8 及更早IE版本不支援 addEventListener() 方法,Opera 7.0 及 Opera 更早版本也不支援。 但是,對於這些不支援該函式的瀏覽器,你可以使用 attachEvent() 方法來新增事件控制代碼。對於事件繫結相

JS中事件繫結函式事件捕獲事件冒泡

1 事件繫結:事件與函式繫結的方式 1.1 元素.onclick這種形式,如下: 1 <div id="div1">aaa</div> 2 3 <script type="text/javascript">