文章出處

一、事件

事件階段

一般的,事件分為三個階段:捕獲階段、目標階段和冒泡階段。

(1)捕獲階段(Capture Phase)

  事件的第一個階段是捕獲階段。事件從文檔的根節點流向目標對象節點。途中經過各個層次的DOM節點,并在各節點上觸發捕獲事件,直到到達事件的目標節點。捕獲階段的主要任務是建立傳播路徑,在冒泡階段,事件會通過這個路徑回溯到文檔跟節點。

  或這樣描述:

  任何事件產生時,如點擊一個按鈕,將從最頂端的容器開始(一般是html的根節點)。瀏覽器會向下遍歷DOM樹直到找到觸發事件的元素,一旦瀏覽器找到該元素,事件流就進入事件目標階段

(2)目標階段(Target Phase)

  當事件到達目標節點的,事件就進入了目標階段。事件在目標節點上被觸發,然后會逆向回流,直到傳播至最外層的文檔節點。

(3)冒泡階段(Bubble Phase)

  事件在目標元素上觸發后,并不在這個元素上終止。它會隨著DOM樹一層層向上冒泡,回溯到根節點。
  冒泡過程非常有用。它將我們從對特定元素的事件監聽中釋放出來,如果沒有事件冒泡,我們需要監聽很多不同的元素來確保捕獲到想要的事件。

事件委托

事件委托是一種由其它元素而非事件目標元素來響應事件產生的行為的思想。

通俗的講,事件就是onclick,onmouseover,onmouseout,等就是事件,委托呢,就是讓別人來做,這個事件本來是加在某些元素上的,然而你卻加到別人身上來做,完成這個事件。

也就是:利用冒泡的原理,把事件加到父級上,觸發執行效果。

好處呢:1.提高性能; 2. 易于維護;

比如用document元素來處理按鈕的點擊行為,用ul元素來處理其子元素li的事件。

有多種方法來處理事件委托。標準方法來源于原生瀏覽器的功能。瀏覽器以一種特定的工作流程來處理事件,并支持事件捕獲和事件冒泡。W3C關于瀏覽器怎么支持事件的文檔:W3C DOM Level 3 Events。一些JS庫和框架公開了其它方式,如發布/訂閱模型(將在后文提及)。

事件冒泡

(1)為什么要阻止事件冒泡

  有種可能是,某個DOM節點綁定了某事件監聽器,本來是想當該DOM節點觸發事件,才會執行回調函數。結果是該節點的某后代節點觸發某事件,由于事件冒泡,該DOM節點事件也會觸發,執行了回調函數,這樣就違背了最初的本意了。

(2)如何阻止事件冒泡

  1. stopPropagation:告訴DOM事件停止冒泡
  2. stopImmediatePropagation,它不僅停止冒泡,也會阻止這個元素上其它監聽當前事件的處理程序觸發。然而,停止傳播事件時要小心,因為你不知道是否有其它上層的DOM元素可能需要知道當前事件。
  3. preventDefault,這個方法會阻止瀏覽器處理事件的默認行為。一個常見示例就是鏈接,使用鏈接執行UI操作是一種常見的做法。然而,當我們不希望鏈接跟普通被激活的鏈接一樣會在新標簽頁打開一個新頁面,就可以使用preventDefault方法來阻止這個默認行為。

訂閱發布模式

  還有其它實現事件委托的方法可以考慮,其中值得一提的就是發布/訂閱模型。發布/訂閱模型也稱為了廣播模型,牽涉到兩個參與者。通常,兩個參與者在DOM中并沒有緊密的聯系,而且可能是來自兄弟的容器。可以給它們共同的祖先元素設置監聽處理程序,但是如果共同的祖先元素在DOM樹中處于較高層次(離根節點比較近),就會監聽很多同輩元素的事件,會造成意想不到的結果;當然,也可能存在邏輯或結構原因要分開這兩個元素。

  發布/訂閱模型也能自定義事件。發布/訂閱模型從一個元素發送消息后并向上遍歷,有時也向下遍歷,DOM會通知遍歷路徑上的所有元素事件發生了。在下面的示例中,JQuery通過trigger方法傳遞事件。

二、this

this 關鍵字在JavaScript中的一種常用方法是指代碼當前上下文。

  • 如果this沒有被設置,則默認指向全局對象,其通常是window
  • 如果一個函數中運行了一個內聯函數,比如一個事件監聽器,則this指向內聯函數的源代碼。例如,當設置一個按鈕的單擊處理程序,this將引用匿名函數內的按鈕。
  • 如果函數是一個對象的構造函數,this指向新對象。
  • 如果函數被定義在一個對象上,然后調用對象時,this指向該對象。
  • 在異步編程中,this可以很容易改變過程中一個功能操作。保持處理程序上下文的一個小技巧是將其設置到閉包內的一個變量,當在上下文改變的地方調用一個函數時,如setTimeout,你仍然可以通過該變量引用需要的對象。

例子

(1)如果該函數是被當做某一個對象的方法,那么該函數的this指向該對象;

var car= {
    modelNum: "Benz"
}
function f() {
    alert(this.modelNum+ ":hello world")
}//this就是car這個對象
Benz.sayHi = f
Benz.sayHi() ;

 

(2)函數之內調用 
  當函數中有 this,其實就意味著它被當做方法調用,之間調用相當于把他當做window對象的方法,this指向window.

function func() {
    alert(this) // this指向window
}
func()

 

總之,如果this沒有被設置,則默認指向全局對象,其通常是window 

操作this的另一種方式是通過call、apply和bind。三種方法都被用于調用一個函數,并能指定this的上下文,你可以讓代碼使用你規定的對象,而不是依靠瀏覽器去計算出this指向什么。

 

 

參考:

JavaScript面試問題:事件委托和this 

淺談事件委托和this用法

事件冒泡和事件捕獲


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()