1. 程式人生 > >HTML 事件(三) 事件流與事件委託

HTML 事件(三) 事件流與事件委託

    本篇主要介紹HTML DOM中的事件流和事件委託。

其他事件文章

3. HTML 事件(三) 事件流與事件委託

目錄

1. 事件流

  1.1 何為事件流

2. 事件委託

    2.3.2 on()

1. 事件流 (Event Flow)

1.1 何為事件流

簡單來說HTML的元素會出現巢狀的關係,比如:一個Div嵌套了一個Button按鈕,當2個元素都註冊了click點選事件。點選裡面的Button按鈕時,Div的click事件也會觸發。

那麼問題來了,既然都會觸發,得有個觸發的順序吧?是按照Div → Button這樣的順序觸發,還是按照Button → Div的順序觸發?

在之前,兩大瀏覽器廠商網景和微軟都有各自的觸發順序:

網景的瀏覽器採用捕獲方式:按照Div → Button這樣的順序觸發.

而微軟的瀏覽器採用冒泡方式:按照Button → Div的順序觸發。

在2級DOM事件規範制定時乾脆合二為一:事件流同時包含了這2個階段。

1.2 事件流的三個階段

1.2.1 三個階段

2級DOM事件規範制定了事件流的三個階段:捕獲階段目標階段冒泡階段

捕獲階段(Capture Phase):事件從最外層的window物件到目標節點的父節點依次觸發的階段。(從外到內)

目標階段(Target Phase):事件在目標節點上觸發時的階段。

冒泡階段

(Bubbing Phase):事件從目標節點的父節點到最外層的window物件依次觸發的階段。(從內到外)

1.2.2 示例圖

 

1.3 addEventListener()註冊事件流的階段

元素物件通過addEventListener()註冊事件時,此方法的的第三個引數可設定本次註冊是捕獲階段還是冒泡階段

1.3.1 addEventListener()方法說明

語法:EventTarget.addEventListener(eventName, eventHandler [, useCapture] )

引數

①eventName {string} :所要註冊的事件名稱,不區分大小寫。此名稱不需要像註冊事件屬性那樣在字首加上"on

"。如註冊滑鼠點選事件,寫為click。

②eventHandler {function | function Object} :函式或者函式物件。事件觸發時所需要執行的函式;當使用函式物件多次註冊同一事件時,只當註冊一遍。

③useCapture {boolean} 可選 :是否處於捕獲階段,預設為false。

  |-true:當前註冊的事件為捕獲階段。

  |-false:當前註冊的事件不為捕獲階段,為冒泡階段。

1.3.2 示例

示例使用到Event事件物件的部分屬性:

屬性 readonly Object currentTarget :只讀,獲取正在處理此事件的物件。

屬性 readonly int eventPhase :只讀,表示事件的處理階段:0表示沒有正在處理,1表示捕獲階段,2表示目標階段,3表示冒泡階段。

屬性 readonly Object target :只讀,獲取觸發此事件的物件。

function clickHandle(e){
    console.log("事件階段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
} 

window.addEventListener('click',clickHandle,false);
window.addEventListener('click',clickHandle,true);
document.addEventListener('click',clickHandle,false);
document.addEventListener('click',clickHandle,true);
document.documentElement.addEventListener('click',clickHandle,false);
document.documentElement.addEventListener('click',clickHandle,true);
document.body.addEventListener('click',clickHandle,false);
document.body.addEventListener('click',clickHandle,true);
document.getElementById('div').addEventListener('click',clickHandle,false);
document.getElementById('div').addEventListener('click',clickHandle,true);
document.getElementById('btn').addEventListener('click',clickHandle,false);
document.getElementById('btn').addEventListener('click',clickHandle,true);

1.4 阻止事件流的傳播

Event 事件物件的stopPropagation()、stopImmediatePropagation()方法可阻止事件流的後續傳播。

stopImmediatePropagation()方法除了阻止事件流傳播還會阻止當前事件在此元素的後續事件處理程式。

事件流的三個階段呼叫這2個方法,會有不同的阻止傳播方式:

1.4.1 在捕獲階段呼叫

說明:在捕獲階段呼叫stopPropagation()方法時,此元素後續的事件流都會阻止,包括捕獲階段、目標階段、冒泡階段

示例:在1.3.2示例程式碼中的body元素捕獲階段呼叫此方法

document.body.addEventListener('click',function(e){
    console.log("事件階段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
    e.stopPropagation();
},true);

結果:事件流在body的捕獲階段就截至了,後續的階段都沒有執行

 

1.4.2 在目標階段呼叫

說明:在目標段呼叫stopPropagation()方法時,捕獲階段和目標階段會執行完畢,冒泡階段不會被執行

示例:在1.3.2示例程式碼中的button按鈕元素目標階段呼叫此方法

document.getElementById('btn').addEventListener('click',function(e){
    console.log("捕獲階段註冊:事件階段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
    e.stopPropagation();
},false);
document.getElementById('btn').addEventListener('click',function(e){
    console.log("冒泡階段註冊:事件階段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
    e.stopPropagation();
},true);

結果:捕獲階段和目標階段執行完畢,冒泡階段未被執行。

1.4.3 在冒泡階段呼叫

說明:在冒泡段呼叫stopPropagation()方法時,捕獲階段和目標階段會執行完畢,元素後續的冒泡階段不會被執行

示例:在1.3.2示例程式碼中的body冒泡階段呼叫此方法

document.body.addEventListener('click',function(e){
    console.log("事件階段:"+e.eventPhase+';target:'+e.target+';currentTarget:'+e.currentTarget)
    e.stopPropagation();
},false);

結果:捕獲階段和目標階段執行完畢,body後續的冒泡階段未被執行

2. 事件委託(Event Delegate)

2.1 何為事件委託

HTML元素含有巢狀關係,並且事件流含有冒泡階段。子元素的觸發事件會冒泡到父元素的相同事件上。

一般情況只需給子元素註冊特定的事件處理程式即可,但當子元素過多或頻繁的進行增減操作怎麼辦?

比如一個ul包含了幾十個li元素,對每個li元素進行單獨的事件註冊會影響效能。而現只要在父元素註冊事件監聽器,等待li事件觸發後的冒泡階段即可。

簡單來說事件委託就是父元素監聽子元素的冒泡事件

2.2 ul、li場景示例

Div容器包含了多個li子元素,在Div容器註冊事件委託。

HTML程式碼

<div id="div">
    <ul id="ul" >
        <li data-key="北京">北京</li>
        <li data-key="上海">上海</li>
        <li data-key="杭州">杭州</li>
    </ul>
</div>

JS程式碼

document.getElementById('div').addEventListener('click',function(e){
    var value=e.target.attributes['data-key'].value; // 獲取目標階段元素的'data-key'屬性的值
    console.log(value); 
});

2.3 JQuery的事件委託

在JQuery中,父元素可呼叫delegate()、on()作為事件委託使用。

2.3.1 delegate()

語法:$('父元素').delegate( selector [, eventType] [, eventData], handler )

引數

①selector {string} :子元素的選擇器、

②eventType {eventType} 可選 :觸發的事件型別。如:click。

③eventData {object} 可選 :觸發事件時event.data指向的值。

④handler {function} :事件註冊的處理程式。

示例

$('#div').delegate('li', 'click', function() {
    var v = $(this).data('key');
    console.log(v);
});

2.3.2 on()

說明:JQuery1.7版本開始時,推薦on()代替delegate()方法。

語法:$('元素').on( events [, selector ] [, data ], handler )

引數

①events {string} :一個或多個事件名稱。

②selector {string} 可選 :子元素選擇器。若無此值,表示元素註冊本身的事件。若含有此值,表示只有子元素的事件觸發,才會觸發註冊的事件。

③data {object} 可選 :觸發事件時的event.data指向的值。

④handler {function} :事件註冊的處理程式。

示例

$('#div').on('click','li',function(e) {
    var v = $(this).data('key');
    console.log(v);
});

相關推薦

HTML 事件() 事件事件委託

    本篇主要介紹HTML DOM中的事件流和事件委託。 其他事件文章 3. HTML 事件(三) 事件流與事件委託 目錄 1. 事件流   1.1 何為事件流 2. 事件委託     2.3.2 on() 1. 事件流 (Event Flow

翻譯:Libevent參考手冊第章:事件迴圈一起工作 (五) (轉)

預設情況下,event_base_loop()函式執行event_base直到其中沒有已經註冊的事件為止。執行迴圈的時候,函式重複地檢查是否有任何已經註冊的事件被觸發(比如說,讀事件的檔案描述符已經就緒,可以讀取了;或者超時事件的超時時間即將到達)。如果有事件被觸發,函式標記被觸發的事件為“啟用的”,並且執行

jquery學習筆記之事件繫結on事件解綁off用法

on()的多事件繫結 之前學的滑鼠事件,表單事件與鍵盤事件都有個特點,就是直接給元素繫結一個處理函式,所有這類事件都是屬於快捷處理。翻開原始碼其實可以看到,所有的快捷事件在底層的處理都是通過一個”on”方法來實現的。jQuery on()方法是官方推

nodejs事件的監聽事件的觸發

一、事件機制的實現 Node.js中大部分的模組,都繼承自Event模組(http://nodejs.org/docs/latest/api/events.html )。Event模組(events.EventEmitter)是一個簡單的事件監聽器模式的實現。具有add

js事件階段事件委託

首先明確一個概念, js中事件包含三個階段: 捕獲 到達目標 冒泡  事件委託:將子元素上的事件委託給父元素監聽,從而無需對每一個子元素設定監聽事件。例如ul巢狀多個li,要點選時alert每個li的innerText <ul id="

C#學習筆記()—–C#高階特性中的委託事件(中)

C#高階特性中的委託與事件(中) 事件 委託本身又是一個更大的模式(pattern)的基本單位,這個模式稱為publish-subscribe(釋出——訂閱)。委託的使用及其對publish-subscribe模式的支援是本章的重點。本章描述的所有內容幾乎

委託事件-委託事件案例(

前言   這兩天一直在想如何結合實際案例來結束委託與事件的講解,下面講解兩個事例,用來加深對委託及事件的理解。 事例一(分頁功能)   本場景是用來講解使用的,具體內容功能需自行填補實現。用委託加事件來實現分頁功能的通用。按上一節講解中的邏輯處理,分為訂閱者和釋出者,一樣的可以先定義訂閱者感興趣的物件,

JS中的事件監聽事件

pan 交互 ack 其他 獲得 發生 listen 監聽器 pre 事件監聽:   使用監聽器(eventListener)來預定事件,在傳統軟件工程中稱成為觀察者模式   執行某種操作時(特定的交互瞬間),會產生對象,對象會沿事件流的方向傳播。 事件流:   事件流有

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

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

JavaScript的事件、DOM模型、事件模型以及內置對象詳解(

dde function n) 事件冒泡 字符 nds rep == 防止 JS中的事件 JS中的事件分類   1.鼠標事件:     click/dbclick/mouseover/mouseout   2.HTML事件:     onload/onunload

js事件事件冒泡的應用----事件委託

什麼是事件委託? 它還有一個名字叫事件代理。 JavaScript高階程式設計上講: 事件委託就是利用事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件。 用取快遞來解釋這個現象,大家認真領會一下事件委託到底是一個什麼原理: 有三個同事預計會在週一收到快遞。為簽收快遞,有兩種辦法:一

C#委託事件學習筆記

委託事件學習筆記 本文是學習委託和事件的筆記,水平有限,如有錯漏之處,還望大神不吝賜教。 什麼是委託?從字面意思來解釋,就是把一個動作交給別人去執行。在實際開發中最常用的就是使一個方法可以當做一個引數傳遞,以便在方法中可以根據實際情況實現不同的功能。 什麼是事件?事件就是發生的事情,例如點選了一

python+selenium:鼠標事件鍵盤事件

圖片 png class 技術 context inf web tex 雙擊 # 1、鼠標事件:# 每個模擬事件後需加.perform() 才會執行# context_click() 右擊# double_click() 雙擊# drag_and_drop(sour

Unity之C#——委託事件,觀察者模式,貓和老鼠事例

委託與事件,觀察者模式,貓和老鼠事例     在Unity遊戲開發中,我們經常需要在一個類中,呼叫另一個類中的方法,比如,當玩家進入到某個地方,敵人就開始攻擊玩家。這時就需要利用委託與事件,設計觀察者模式。 此處我們利用貓和老鼠來簡單描述: 程式碼如下: Ca

委託事件聯合使用

1、建立委託 /// <summary> /// 顧客走進飯店 /// 把選單給顧客 /// </summary> /// <param name="cusobj">顧客<

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

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

理解Javascript中的事件繫結事件委託(轉載)

最近在深入實踐js中,遇到了一些問題,比如我需要為動態建立的DOM元素繫結事件,那麼普通的事件繫結就不行了,於是通過上網查資料瞭解到事件委託,因此想總結一下js中的事件繫結與事件委託。 事件繫結 最直接的事件繫結:HTML事件處理程式 如下示例程式碼,通過節點屬性顯式宣

C#中委託事件的學習小結(一)

最近又學習了一些C#的小知識點,在此釋出部落格記錄一下。 一、委託 C#中的委託的關鍵字是delegate,我們可以使用委託型別來將已有的方法例項化出來,也可以將我們自己定義的方法作為引數來傳遞。 例如: private delegate string GetAStri

基礎知識篇:委託事件

委託是對函式的封裝,可以當做給方法的特徵指定一個名稱。而事件則是委託的一種特殊形式,當發生有意義的事的時候,事件物件 處理通知過程。 注意 1.委託是一種引用方法的型別。一旦為委託分配了方法,委託就與該方法具有完全相同的行為。 2.事件是在發生其它類或物件關注的事情的時

C#委託事件之----委託

C#委託與事件之委託 整理了一下委託的幾種使用方法,都在程式碼裡面了 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst