javascript事件概述

事件基本概念

事件類型:用來說明發生什么類型事件的字符串,即事件名。
  事件目標:發生事件的對象。當談論事件時,會同時指明類型和目標。
  事件處理程序:處理或響應事件的函數,即事件監聽程序。
  事件對象:與特定事件相關并且包含有關該事件詳細信息的對象。事件對象作為參數傳遞給事件處理程序(IE8之前的瀏覽器通過Event獲取事件對象)。
  事件傳播:事件發生時,事件會由window發出,不斷經過下一級節點直到目標節點,到達目標節點后,事件會按原路線返回window,事件從目標節點返回window的過程就是事件傳播,又稱冒泡階段。在事件傳播階段可以通過事件對象阻止事件傳播。
  事件捕獲: 事件發生時,事件會由window發出,不斷經過下一級節點直到目標節點,這一過程就是事件捕獲,又稱捕獲階段。在事件捕獲階段可以通過事件對象阻止事件捕獲。IE8之前的瀏覽器不支持事件捕獲。

常見事件類型

1.Window事件
  發生在瀏覽器窗口上的事件,部分事件的事件類型會與文檔中的某些事件類型同名,包括文檔以及外部資源完全加載時觸發的load事件;瀏覽器窗口文檔跳轉到新文檔時觸發unload事件,該事件觸發時不影響文檔跳轉;在文檔跳轉之前如果需要征得用戶同意,可以使用beforeunload事件;瀏覽器窗口加載文檔過程中出錯時觸發error事件;瀏覽器窗口尺寸改變時觸發resize事件,滾動條滾動時觸發scroll事件;瀏覽器窗口獲取焦點或者失去焦點時,分別觸發focus事件,blur事件;
  2.DOM事件
  主要有表單事件,鼠標事件,鍵盤事件,文本事件,文檔加載事件。
  表單事件包括提交表單時觸發submit事件;重置表單時觸發reset事件;表單元素內容修改時觸發change事件;得到焦點,失去焦點時觸發focus事件,blur事件;表單元素的點擊時觸發click事件等;
  鼠標事件包括點擊鼠標時觸發click事件;移動鼠標時觸發mousemove事件;按下,釋放鼠標按鍵時觸發mousedown事件,mouseup事件;點擊右鍵時觸發contextmenu事件,可以用來修改上下文菜單;連續點擊兩次鼠標按鍵時觸發dblclick事件;鼠標滑到元素上,離開元素時觸發mouseover事件,mouseup事件,IE中對應mouseenter事件,mouseleave事件;
  鍵盤事件包括按下,釋放按鍵時觸發的keydown事件,keyup事件;keydown事件與keyup事件之前會觸發keypress事件;
  文本事件,使用webkit內核的瀏覽器支持textInput事件,該事件在產生可打印字符時觸發;
  3.HTML5事件
  主要是指HTML5標準化的事件以及新增的事件。

事件傳播

一個事件發生時,是事件先從文檔根節點流向事件目標,然后在事件目標上觸發事件,然后再回溯到文檔根節點,即事件傳播有三個階段,從文檔根節點流向事件目標是捕獲階段,到達事件目標是目標階段,然后從事件目標到文檔根節點是冒泡階段(IE8之前的瀏覽器不支持捕獲階段,所以其事件傳播,只有冒泡階段)。完整流程如下圖。

事件流.png

這里有一個Demo形象的模擬了事件傳播過程。

事件代理

瀏覽器都支持冒泡階段,我們可以利用瀏覽器的冒泡機制,通過監聽父級節點來實現監聽子節點的功能,這就是事件代理的概念。
  使用事件代理的好處:
    1.減少事件綁定次數,提高頁面性能;
    2.可以監聽動態變化的DOM結構,前提是父級節點不是動態變化的,子節點可以動態變化。
  原理是在父級節點綁定相應事件處理程序,當對應事件在子節點觸發時通過冒泡階段把事件傳遞到父節點,在父節點觸發事件處理程序,再根據事件對象的target屬性可以獲取到是哪個事件目標,然后就可以根據不同的事件目標,來實現不同的業務邏輯。

事件監聽(綁定,注冊)

主要有以下方式來注冊事件處理程序:
  1.通過設置事件目標的事件屬性,這些事件屬性主要是由“on+事件名”組成。
  例如:
    document.getElementByTagName("a").onclick = function(){console.log("This is a click event");};
通過這種方式注冊事件處理程序,同一個事件目標一次只能注冊一個事件處理程序。
  2.通過設置標簽屬性注冊事件處理程序。
  例如:
    <a onclick="console.log('This is a click event')"></a>
通過這種方式只需要把函數體賦值給事件屬性即可,同樣的這種方式一次也只能注冊一個事件處理程序。
  3.支持標準事件模型的瀏覽器(IE8以及IE8之前的瀏覽器除外)中,事件目標對象中都有一個addEventListener()方法,可以使用這個方法給事件目標注冊事件處理程序。使用這個方法一次可以給事件目標注冊多個不同的事件處理程序,使用不同的事件處理程序參數多次調用即可,觸發時根據注冊順序先后執行事件處理程序。相同的事件處理程序參數多次調用這個方法注冊,也只能注冊一次。
  這個方法的完整定義:

element.addEventListener(event, function, useCapture)
event  必傳參數      指定事件名
function    必傳參數      事件處理程序
userCapture   可選參數      默認為false,指定事件處理程序在冒泡階段執行;ture,指定事件處理程序在捕獲階段執行

4.不支持標準事件模型的瀏覽器(IE8以及IE8之前的瀏覽器)中,事件目標可以使用attachEvent()方法來注冊事件處理程序。相同的事件處理程序使用這個方法可以被注冊多次。
  這個方法的完整定義:

element.attachEvent(event, function, useCapture)                   
event  必傳參數      指定 "on"+事件名
function    必傳參數      事件處理程序

由于IE8以及IE8之前瀏覽器不支持事件捕獲,所以這個方法只有兩個參數。

注意:IE9,IE10即支持addEventListener()方法又支持attachEvent()方法來注冊事件處理程序,但是IE8,IE7,IE6,IE5瀏覽器只支持attachEvent()方法注冊事件處理程序。

事件調用順序

1.通過方式1,2注冊的事件處理程序優先執行。
  2.通過方式3注冊的事件處理程序按照注冊順序執行。
  3.通過方式4注冊的事件處理程序執行順序不定,(測試發現IE9,IE10按照注冊順序正序執行,IE8按照注冊順序倒序執行)。

事件解綁,注銷

通過方式1,2注冊的事件無法解綁。
  通過方式3注冊的事件處理程序可以通過 removeEventListener()方法解綁, removeEventListener()方法有三個參數,第一個參數與addEventListener()方法一樣,需要傳事件名;第二個參數需要傳 用addEventListener()方法注冊的事件處理程序函數名,即想要解綁addEventListener()方法注冊的事件處理程序,那么在注冊時必須用事先聲明好的函數,不能用匿名函數注冊;第三個參數與addEventListener()方法的第三個參數一樣。
  通過方式4注冊的事件處理程序可以通過detachEvent()方法解綁,detachEvent()方法參數與attachEvent()方法參數一樣,使用時和 removeEventListener()方法類似。

事件取消

1.取消發生該事件時瀏覽器的默認操作
    通過方式1,2注冊的事件處理程序,可以直接返回false來告訴瀏覽器不要執行事件相關的默認操作。
    通過方式3注冊的事件處理程序,可以直接調用事件對象的preventDefault()方法來告訴瀏覽器不要執行事件相關的默認操作。
    通過方式4注冊的事件處理程序,可以通過設置事件對象的returnValue屬性為false來告訴瀏覽器不要執行事件相關的默認操作。
  2.取消事件傳播
    通過方式1,2注冊的事件處理程序,不能取消事件傳播
    通過方式3注冊的事件處理程序,可以直接調用事件對象的stopPropagation()方法來阻止事件傳播。
    通過方式4注冊的事件處理程序,可以直接設置事件對象的cancelBubble屬性為true來阻止事件傳播。

自定義事件

對于支持標準事件模型的瀏覽器可以通過以下方式實現自定義事件
初始化事件類型
var event = new Event('myEvent');
或者

var event = document.createEvent('Event');
event.initEvent('myEvent',true,true);

綁定事件
element.addEventListener('myEvent',function(){});
解綁事件
element.removeEventListener('myEvent',funcName);
觸發事件
element.dispatchEvent(event);
  針對支持標準事件模型的瀏覽器處理事件時大體流程相似,主要的區別有兩點,自定義事件需要初始化事件類型,以及使用dispatchEvent方法觸發事件

IE瀏覽器注冊自定義事件可以通過IE瀏覽器的私有的事件屬性propertychange實現,具體參考漫談js自定義事件、DOM/偽DOM自定義事件

如果引用了jquery,使用自定義事件就比較簡單了
綁定事件
element.on("myEvent",function(){});
解綁事件
element.off("myEvent");
觸發事件
element.trigger("myEvent");

自定義事件與內置事件的區別關注點不一樣,自定義事件關注的是執行事件的標簽,觸發時機由程序控制;而內置事件關注的是觸發事件的標簽,觸發時機由瀏覽器控制。自定義事件詳細可以參考 Introducing custom events

資料來源

1.js權威指南
2.http://blog.jobbole.com/52430/
3.http://www.admin10000.com/document/6089.html
4.http://learn.jquery.com/events/introduction-to-custom-events/

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,915評論 18 139
  • JavaScript 程序采用了異步事件驅動編程模型。在這種程序設計風格下,當文檔、瀏覽器、元素或與之相關的對象發...
    劼哥stone閱讀 1,274評論 3 11
  • 一、JS前言 (1)認識JS 也許你已經了解HTML標記(也稱為結構),知道了CSS樣式(也稱為表示),會使用HT...
    凜0_0閱讀 2,798評論 0 8
  • 第1章 認識JS JavaScript能做什么?1.增強頁面動態效果(如:下拉菜單、圖片輪播、信息滾動等)2.實現...
    mo默22閱讀 1,326評論 0 5
  • 節后總是會產生惰性,工作不在狀態,參加的活動也不在狀態,錯漏百出。 自己想象中的效果與實際遇到的效果好想差了十萬八...
    諪諪_0c2f閱讀 193評論 0 0