JavaScript:深入理解事件流 & 事件處理程序

** 定義:**
事件:用戶或瀏覽器自身執行的某種動作。
事件流:描述的是從頁面中接收事件的順序,也可理解為事件在頁面中傳播的順序。
事件處理程序:響應某個事件的函數就叫做事件處理程序(或事件偵聽器)。

事件流

**(1)事件冒泡 **
??IE 的事件流叫做事件冒泡(event bubbling),即事件開始時由最具體的元素(文檔中嵌套層次最深的那個節點)接收,然后逐級向上傳播到較為不具體的節點(文檔)。如下圖所示:

IE9、Firefox、Chrome 和 Safari 則將事件一直冒泡到 window 對象。

**(2)事件捕獲 **
??事件捕獲的思想與事件冒泡的思想幾乎完全相反,是不太具體的節點應該更早接收到事件,而最具體的節點應該最后接收到事件。事件捕獲的用意在于在事件到達預定目標之前捕獲它。如下圖所示:

**(3)DOM事件流 **
??“DOM2級事件”規定的事件流包括三個階段:事件捕獲階段、處于目標階段 和 事件冒泡階段。

  • 首先發生的是事件捕獲,為截獲事件提供了機會。
  • 然后是實際的目標接收到事件。
  • 最后一個階段是冒泡階段,可以在這個階段對事件做出響應。

??在 DOM 事件流中,實際的目標( <div> 元素)在捕獲階段不會接收到事件。這意味著在捕獲階段,事件從 document 到 <html> 再到 <body> 后就停止了。下一個階段是“處于目標”階段,于是事件在 <div>上發生,并在事件處理中被看成冒泡階段的一部分。然后,冒泡階段發生,事件又傳播回文檔。

??IE9,Opera,Firefox,Chrome 和 Safari 都支持 DOM 事件流;IE8 及更早版本不支持 DOM 事件流。

事件處理程序

??響應某個事件的函數就叫做事件處理程序(或事件偵聽器)。事件處理程序的名字以 "on" 開頭,因此click 事件的事件處理程序就是 onclick,load 事件的事件處理程序就是 onload 。為事件指定處理程序的方式有以下幾種:

** (1)HTML事件處理程序 **

  <input type="button" value="Click Me" onclick="alert('Clicked')" />

缺點:

  • 存在時差問題:因為用戶可能會在HTML 元素一出現在頁面上就觸發相應的事件,但當時的事件處理程序有可能尚不具備執行條件,就會引發錯誤。
  • 這樣擴展事件處理程序的作用域鏈在不同瀏覽器中會導致不同結果。不同 JavaScript引擎遵循的標識符解析規則略有差異,很可能會在訪問非限定對象成員時出錯。
  • HTML 與 JavaScript 代碼緊密耦合。如果要更換事件處理程序,就要改動兩個地方:HTML 代碼和 JavaScript 代碼。

** (2)DOM0級事件處理程序 **

??即將一個函數賦值給一個事件處理程序屬性。

  var btn = document.getElementById("myBtn");
  btn.onclick = function(){
      alert("Clicked");
  };
  btn.onclick = null; //刪除事件處理程序

優點:

  • 簡單
  • 可跨瀏覽器

** (3)DOM2級事件處理程序 **

  addEventListener(事件名稱,事件函數,是否捕獲);        //添加事件處理程序
  removeEventListener(事件名稱,事件函數,是否捕獲);     //移除事件處理程序

所有 DOM 節點中都包含這兩個方法。

優點:可以添加多個事件處理程序。

??通過 addEventListener() 添加的事件處理程序只能使用 removeEventListener() 來移除。所以通過addEventListener()添加的匿名函數將無法移除。

??大多數情況下,都是將事件處理程序添加到事件流的冒泡階段,這樣可以最大限度地兼容各種瀏覽器。最好只在需要在事件到達目標之前截獲它的時候將事件處理程序添加到捕獲階段。如果不是特別需要,不建議在事件捕獲階段注冊事件處理程序。

** (4)IE事件處理程序 **

  attachEvent( 事件名稱,事件函數 );    //添加事件處理程序
  detachEvent( 事件名稱,事件函數 );    //移除事件處理程序

由于 IE8 及更早版本只支持事件冒泡,所以通過attachEvent() 添加的事件處理程序都會被添加到冒泡階段。

注:例如 添加點擊事件,attachEvent() 的第一個參數是 "onclick",而非 DOM 的 addEventListener() 方法中的"click" 。

??在 IE 中使用 attachEvent() 與使用 DOM0 級方法的主要區別在于事件處理程序的作用域。在使用DOM0 級方法的情況下,事件處理程序會在其所屬元素的作用域內運行;在使用 attachEvent() 方法的情況下,事件處理程序會在全局作用域中運行,因此 this 等于 window 。

??attachEvent()也可以用來為一個元素添加多個事件處理程序。不過,與 DOM方法不同的是,這些事件處理程序不是以添加它們的順序執行,而是以相反的順序被觸發。例如:下面的例子,點擊按鈕,首先看到的是"Hello world!",然后是"Clicked”。

  var btn = document.getElementById("myBtn");
  btn.attachEvent("onclick", function(){
      alert("Clicked");
  });
  btn.attachEvent("onclick", function(){
      alert("Hello world!");
  });

** (5)跨瀏覽器的事件處理程序 **
??首先要創建的方法是 addHandler() ,它的職責是視情況分別使用 DOM0 級方法、DOM2 級方法或 IE 方法來添加事件。這個方法屬于一個名叫 EventUtil 的對象。
??addHandler() 方法接受 3 個參數:要操作的元素、事件名稱和事件函數。

var EventUtil={ 
   addHandler:function(element,type,handler){            //添加事件
      if(element.addEventListener){ 
         element.addEventListener(type,handler,false);  //使用DOM2級方法添加事件
      }else if(element.attachEvent){                    //使用IE方法添加事件
         element.attachEvent("on"+type,handler);
      }else{
         element["on"+type]=handler;                    //使用DOM0級方法添加事件
      }
   },  

   removeHandler:function(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;
      }
   }
}

使用 EventUtil 對象

  var btn = document.getElementById("myBtn");
  var handler = function(){
      alert("Clicked");
  };
  EventUtil.addHandler(btn, "click", handler);
  EventUtil.removeHandler(btn, "click", handler);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容