首頁 web前端 js教程 深入分析原生JavaScript事件_基礎知識

深入分析原生JavaScript事件_基礎知識

May 16, 2016 pm 04:23 PM
javascript 事件 原生

 JQuery這種Write Less Do More的框架,用多了難免會對原生js眼高手低。

     小菜其實不想寫這篇博客,貌似很初級的樣子,但是看到網絡上連原生js事件綁定和解除都說不明白,還是決定科普一下了。

     先聲明,小菜懂的也不是很多,只是把我的思路和大家分享一下。

DOM0事件模型

     事件模型不斷發展,早期的事件模型稱為DOM0等級。

     DOM0事件模型,所有的瀏覽器都支援。

     直接在dom物件上註冊事件名稱,就是DOM0寫法,例如:

複製程式碼 程式碼如下:

document.getElementById("test").onclick = function(e){};

     意思是註冊一個onclick事件。當然,它和這種寫法是一個意思:

複製程式碼 程式碼如下:

document.getElementById("test")["onmousemove"] = function(e){};

     這沒什麼,只不過是兩種存取js物件屬性的方法,[]的形式主要是為了解決屬性名不是合法的標識符,例如:object.123肯定報錯,但是object["123"]就避免了這個問題,同時,[]的寫法,也把js寫活了,用字串表示屬性名稱,可以在運行時動態綁定事件。

     言歸正傳,事件被觸發時,會預設傳入一個參數e,表示事件對象,透過e,我們可以獲得許多有用的信息,例如點擊的座標、具體觸發該事件的dom元素等等。

     以DOM0為基礎的事件,對於同一個dom節點而言,只能註冊一個,後邊註冊的同種事件會涵蓋先前註冊的事件。例如:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 btn.onmousemove = function(e){
   alert("ok");
 };
 btn["onmousemove"] = function(e){
   alert("ok1");
 };

     結果會輸出ok1。

     接下來再說一次this。事件觸發時,this就是指該事件在哪個dom物件上觸發。例如:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 btn.onmousemove = function(e){
   alert(this.id);
 };

     結果輸出test。因為事件就是在id為test的dom節點上註冊的,所以事件觸發時,this當然代表這個dom節點,可以理解為事件是被這個dom節點呼叫的。

     所以,想解除事件就相當簡單了,只需要再註冊一次事件,把數值設為null,例如:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 btn.onclick = function(e){
   alert("ok");
 };
 btn.onclick = null;

     原則是最後註冊的事件要覆蓋之前的,最後一次註冊事件設定成null,也就解除了事件綁定。

     事情還沒結束,DOM0事件模型也牽涉到直接寫在html中的事件。例如:

複製程式碼 程式碼如下:


     以這種方式註冊的事件,同樣遵循覆蓋原則,同樣只能註冊一個,最後一個生效。

     差異就是,這樣註冊的事件,相當於動態呼叫函數(有點eval的意思),因此不會傳入event對象,同時,this指向的是window,不再是觸發事件的dom對象。

DOM2事件模型

     DOM2事件模型相對於DOM0,小菜僅了解以下兩點:

          ·  DOM2支援同一dom元素註冊多個同種事件。

          ·  DOM2新增了捕捉與冒泡的概念。

     DOM2事件透過addEventListener和removeEventListener管理,當然,這是標準。

     但IE8及其以下版本瀏覽器,自娛自樂,搞出了對應的attachEvent和detachEvent,由於小菜才疏學淺,本文不做討論。

     addEventListener當然就是註冊事件,她有三個參數,分別為:"事件名稱", "事件回呼", "捕捉/冒泡"。舉例:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 btn.addEventListener("click", function(e){
   alert("ok");
 }, false);

     事件名稱就不用多說了,相較於DOM0,去掉了前邊的on而已。

     事件回呼也很容易理解,事件觸發了總得通知你吧!回呼時和DOM0一樣,也會預設傳入一個event參數,同時this是指觸發該事件的dom節點。

     最後一個參數是布林型,true代表擷取事件,false代表冒泡事件。其實很好理解,先來個示意圖:

     意思是說,某個元素觸發了某個事件,最先得到通知的是window,然後是document,依次而入,直到真正觸發事件的那個元素(目標元素)為止,這個過程就是捕獲。接下來,事件會從目標元素開始起泡,再依序而出,直到window物件為止,這個過程就是冒泡。

     為什麼要這樣設計?這似乎是由於深厚的歷史淵源,小菜也不怎麼了解,就不亂說了。

     由此可看出,捕捉事件比冒泡事件先觸發。

     假設有這樣的html結構:

複製程式碼 程式碼如下:

 

  

 

     然後我們在外層div上註冊兩個click事件,分別是捕捉事件和冒泡事件,程式碼如下:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 //捕獲事件
 btn.addEventListener("click", function(e){
   alert("ok1");
 }, true);
 //冒泡事件
 btn.addEventListener("click", function(e){
   alert("ok");
 }, false);

     最後,點選內層的div,先彈出ok1,然後彈出ok。結合上邊的原理圖,外層div相當於圖中的body,內層div相當於圖中最下邊的div,證明了捕獲事件先執行,然後執行冒泡事件。

     為什麼要強調點選內層的div呢?因為真正觸發事件的dom元素,必須是內層的,外層dom元素才有機會模擬捕捉事件和冒泡事件,從原理圖上就看出了。

     如果在真正觸發事件的dom元素上註冊捕獲事件和冒泡事件呢?

     html結構同上,js程式碼如下:

複製程式碼 程式碼如下:

 var btnInner = document.getElementById("testInner");
 //冒泡事件
 btnInner.addEventListener("click", function(e){
   alert("ok");
 }, false);
 //捕獲事件
 btnInner.addEventListener("click", function(e){
   alert("ok1");
 }, true);

     當然還是點選內層div,結果是先彈出ok,再彈出ok1。理論上應該先觸發捕獲事件,也就是先彈出ok1,但這裡比較特殊,因為我們是在真正觸發事件的dom元素上註冊的事件,相當於在圖中的div上註冊,由圖可以看出真正觸發事件的dom元素,是捕捉事件的終點,是冒泡事件的起點,所以這裡就不區分事件了,哪個先註冊,就先執行哪個。本例中,冒泡事件先註冊,所以先執行。

     這個道理適用於多個同種事件,比如說一下子註冊了3個冒泡事件,那麼執行順序就按照註冊的順序來,先註冊先執行。例如:

複製程式碼 程式碼如下:

 var btnInner = document.getElementById("testInner");
 btnInner.addEventListener("click", function(e){
   alert("ok");
 }, false);
 btnInner.addEventListener("click", function(e){
   alert("ok1");
 }, false);
 btnInner.addEventListener("click", function(e){
   alert("ok2");
 }, false);

     結果當然依序彈出ok、ok1、ok2。

     為了進一步理解事件模型,還有一種場景,假如說外層div和內層div同時註冊了捕獲事件,那麼點擊內層div時,外層div的事件一定是先觸發的,代碼如下:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 var btnInner = document.getElementById("testInner");
 btnInner.addEventListener("click", function(e){
   alert("ok");
 }, true);
 btn.addEventListener("click", function(e){
   alert("ok1");
 }, true);

     結果是先彈出ok1。

     假如外層div和內層div都是註冊的冒泡事件,點選內層div時,一定是內層div事件先執行,原理相同。

     細心的讀者會發現,對於div嵌套的情況,如果點擊內層的div,外層的div也會觸發事件,這貌似會有問題!

     點選的明明是內層div,但外層div的事件也觸發了,這的確是個問題。

     其實,事件觸發時,會預設傳入一個event對象,前邊提過了,這個event對像上有一個方法:stopPropagation,透過此方法,可以阻止冒泡,這樣外層div就接收不到事件了。程式碼如下:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 var btnInner = document.getElementById("testInner");
 btn.addEventListener("click", function(e){
   alert("ok1");
 }, false);
 btnInner.addEventListener("click", function(e){
   //阻止冒泡
 e.stopPropagation();
   alert("ok");
 }, false);

     終於要說怎麼解除事件了。解除事件語法:btn.removeEventListener("事件名稱", "事件回呼", "擷取/冒泡");

     這和綁定事件的參數一樣,詳細說明下:

          ·  事件名稱,即說明解除哪個事件唄。

          ·  事件回呼,且是一個函數,而這個函數必須與註冊事件的函數是同一個。

          ·  事件類型,布林值,此必須與註冊事件時的類型一致。

     也就是說,名稱、回呼、類型,三者共同決定解除哪個事件,缺一不可。舉例:

複製程式碼 程式碼如下:

 var btn = document.getElementById("test");
 //將回呼儲存在變數中
 var fn = function(e){
   alert("ok");
 };
 //綁定
 btn.addEventListener("click", fn, false);
 //解除
 btn.removeEventListener("click", fn, false);

     若要註冊過的事件能夠解除,必須將回呼函數儲存起來,否則無法解除。

DOM0與DOM2混用

     事情本來就很亂了,這又來個混合使用,還讓不讓人活了。 。 。

     別怕,混合使用完全沒問題,DOM0模型和DOM2模型各自遵循自己的規則,互不影響。

     整體來說,依然是哪個先註冊,哪個先執行,其他就沒什麼了。

後記

     至此,原生js事件已經講的差不多了,小菜僅知道這些而已,歡迎讀者補充其他知識點。

     在實際應用中,真正的行家不會傻傻的真的註冊這麼多事件,一般情況下,只需在最外層dom元素註冊一次事件,然後通過捕獲、冒泡機制去找到真正觸發事件的dom元素,最後根據觸發事件的dom元素提供的資訊去呼叫回呼。

     也就是說,行家會自己管理事件,而不依賴瀏覽器去管理,這樣即可以提高效率,又保證了兼容性,JQuery不就是這麼做的嘛~

     好了,教學到此結束,希望對讀者有幫助!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

jQuery中如何實作select元素的改變事件綁定 jQuery中如何實作select元素的改變事件綁定 Feb 23, 2024 pm 01:12 PM

jQuery是一個受歡迎的JavaScript函式庫,可以用來簡化DOM操作、事件處理、動畫效果等。在web開發中,常常會遇到需要對select元素進行改變事件綁定的情況。本文將介紹如何使用jQuery實作對select元素改變事件的綁定,並提供具體的程式碼範例。首先,我們需要使用標籤來建立一個包含選項的下拉式選單:

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

See all articles