激情欧美日韩一区二区,浪货撅高贱屁股求主人调教视频,精品无码成人片一区二区98,国产高清av在线播放,色翁荡息又大又硬又粗视频

深入分析原生JavaScript事件分析

時(shí)間:2024-09-21 06:13:05 JavaScript 我要投稿
  • 相關(guān)推薦

深入分析原生JavaScript事件分析

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

  小菜其實(shí)不想寫(xiě)這篇博客,貌似很初級的樣子,但是看到網(wǎng)絡(luò )上連原生js事件綁定和解除都說(shuō)不明白,還是決定科普一下了。

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

  DOM0事件模型

  事件模型在不斷發(fā)展,早期的事件模型稱(chēng)為DOM0級別。

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

  直接在dom對象上注冊事件名稱(chēng),就是DOM0寫(xiě)法,比如:

  復制代碼 代碼如下:

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

  意思就是注冊一個(gè)onclick事件。當然,它和這種寫(xiě)法是一個(gè)意思:

  復制代碼 代碼如下:

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

  這沒(méi)什么,只不過(guò)是兩種訪(fǎng)問(wèn)js對象屬性的方法,[]的形式主要是為了解決屬性名不是合法的標識符,比如:object.123肯定報錯,但是object["123"]就避免了這個(gè)問(wèn)題,與此同時(shí),[]的寫(xiě)法,也把js寫(xiě)活了,用字符串表示屬性名稱(chēng),可以在運行時(shí)動(dòng)態(tài)綁定事件。

  言歸正傳,事件被觸發(fā)時(shí),會(huì )默認傳入一個(gè)參數e,表示事件對象,通過(guò)e,我們可以獲取很多有用的信息,比如點(diǎn)擊的坐標、具體觸發(fā)該事件的dom元素等等。

  基于DOM0的事件,對于同一個(gè)dom節點(diǎn)而言,只能注冊一個(gè),后邊注冊的同種事件會(huì )覆蓋之前注冊的。例如:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  btn.onmousemove = function(e){

  alert("ok");

  };

  btn["onmousemove"] = function(e){

  alert("ok1");

  };

  結果會(huì )輸出ok1。

  接下來(lái)再說(shuō)說(shuō)this。事件觸發(fā)時(shí),this就是指該事件在哪個(gè)dom對象上觸發(fā)。例如:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  btn.onmousemove = function(e){

  alert(this.id);

  };

  結果輸出test。因為事件就是在id為test的dom節點(diǎn)上注冊的,事件觸發(fā)時(shí),this當然代表這個(gè)dom節點(diǎn),可以理解為事件是被這個(gè)dom節點(diǎn)調用的。

  所以,想解除事件就相當簡(jiǎn)單了,只需要再注冊一次事件,把值設成null,例如:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  btn.onclick = function(e){

  alert("ok");

  };

  btn.onclick = null;

  原理就是最后注冊的事件要覆蓋之前的,最后一次注冊事件設置成null,也就解除了事件綁定。

  事情還沒(méi)結束,DOM0事件模型還涉及到直接寫(xiě)在html中的事件。例如:

  復制代碼 代碼如下:

  

  通過(guò)這種方式注冊的事件,同樣遵循覆蓋原則,同樣只能注冊一個(gè),最后一個(gè)生效。

  區別就是,這樣注冊的事件,相當于動(dòng)態(tài)調用函數(有點(diǎn)eval的意思),因此不會(huì )傳入event對象,同時(shí),this指向的是window,不再是觸發(fā)事件的dom對象。

  DOM2事件模型

  DOM2事件模型相對于DOM0,小菜僅僅了解如下兩點(diǎn):

  · DOM2支持同一dom元素注冊多個(gè)同種事件。

  · DOM2新增了捕獲和冒泡的概念。

  DOM2事件通過(guò)addEventListener和removeEventListener管理,當然,這是標準。

  但IE8及其以下版本瀏覽器,自?shī)首詷?lè ),搞出了對應的attachEvent和detachEvent,由于小菜才疏學(xué)淺,本文不做討論。

  addEventListener當然就是注冊事件,她有三個(gè)參數,分別為:"事件名稱(chēng)", "事件回調", "捕獲/冒泡"。舉個(gè)例子:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  btn.addEventListener("click", function(e){

  alert("ok");

  }, false);

  事件名稱(chēng)就不用多說(shuō)了,相比DOM0,去掉了前邊的on而已。

  事件回調也很好理解,事件觸發(fā)了總得通知你吧!回調時(shí)和DOM0一樣,也會(huì )默認傳入一個(gè)event參數,同時(shí)this是指觸發(fā)該事件的dom節點(diǎn)。

  最后一個(gè)參數是布爾型,true代表捕獲事件,false代表冒泡事件。其實(shí)很好理解,先來(lái)個(gè)示意圖:

  意思就是說(shuō),某個(gè)元素觸發(fā)了某個(gè)事件,最先得到通知的是window,然后是document,依次而入,直到真正觸發(fā)事件的那個(gè)元素(目標元素)為止,這個(gè)過(guò)程就是捕獲。接下來(lái),事件會(huì )從目標元素開(kāi)始起泡,再依次而出,直到window對象為止,這個(gè)過(guò)程就是冒泡。

  為什么要這樣設計呢?這貌似是由于深厚的歷史淵源,小菜也不怎么了解,就不亂說(shuō)了。

  由此可以看出,捕獲事件要比冒泡事件先觸發(fā)。

  假設有這樣的html結構:

  復制代碼 代碼如下:

  

  

  

  然后我們在外層div上注冊?xún)蓚(gè)click事件,分別是捕獲事件和冒泡事件,代碼如下:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  //捕獲事件

  btn.addEventListener("click", function(e){

  alert("ok1");

  }, true);

  //冒泡事件

  btn.addEventListener("click", function(e){

  alert("ok");

  }, false);

  最后,點(diǎn)擊內層的div,先彈出ok1,后彈出ok。結合上邊的原理圖,外層div相當于圖中的body,內層div相當于圖中最下邊的div,證明了捕獲事件先執行,然后執行冒泡事件。

  為什么要強調點(diǎn)擊內層的div呢?因為真正觸發(fā)事件的dom元素,必須是內層的,外層dom元素才有機會(huì )模擬捕獲事件和冒泡事件,從原理圖上就看出了。

  如果在真正觸發(fā)事件的dom元素上注冊捕獲事件和冒泡事件呢?

  html結構同上,js代碼如下:

  復制代碼 代碼如下:

  var btnInner = document.getElementById("testInner");

  //冒泡事件

  btnInner.addEventListener("click", function(e){

  alert("ok");

  }, false);

  //捕獲事件

  btnInner.addEventListener("click", function(e){

  alert("ok1");

  }, true);

  當然還是點(diǎn)擊內層div,結果是先彈出ok,再彈出ok1。理論上應該先觸發(fā)捕獲事件,也就是先彈出ok1,但是這里比較特殊,因為我們是在真正觸發(fā)事件的dom元素上注冊的事件,相當于在圖中的div上注冊,由圖可以看出真正觸發(fā)事件的dom元素,是捕獲事件的終點(diǎn),是冒泡事件的起點(diǎn),所以這里就不區分事件了,哪個(gè)先注冊,就先執行哪個(gè)。本例中,冒泡事件先注冊,所以先執行。

  這個(gè)道理適用于多個(gè)同種事件,比如說(shuō)一下子注冊了3個(gè)冒泡事件,那么執行順序就按照注冊的順序來(lái),先注冊先執行。例如:

  復制代碼 代碼如下:

  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。

  為了進(jìn)一步理解事件模型,還有一種場(chǎng)景,假如說(shuō)外層div和內層div同時(shí)注冊了捕獲事件,那么點(diǎn)擊內層div時(shí),外層div的事件一定是先觸發(fā)的,代碼如下:

  復制代碼 代碼如下:

  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都是注冊的冒泡事件,點(diǎn)擊內層div時(shí),一定是內層div事件先執行,原理相同。

  細心的讀者會(huì )發(fā)現,對于div嵌套的情況,如果點(diǎn)擊內層的div,外層的div也會(huì )觸發(fā)事件,這貌似會(huì )有問(wèn)題!

  點(diǎn)擊的明明是內層div,但是外層div的事件也觸發(fā)了,這的確是個(gè)問(wèn)題。

  其實(shí),事件觸發(fā)時(shí),會(huì )默認傳入一個(gè)event對象,前邊提過(guò)了,這個(gè)event對象上有一個(gè)方法:stopPropagation,通過(guò)此方法,可以阻止冒泡,這樣外層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);

  終于要說(shuō)說(shuō)怎么解除事件了。解除事件語(yǔ)法:btn.removeEventListener("事件名稱(chēng)", "事件回調", "捕獲/冒泡");

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

  · 事件名稱(chēng),就是說(shuō)解除哪個(gè)事件唄。

  · 事件回調,是一個(gè)函數,這個(gè)函數必須和注冊事件的函數是同一個(gè)。

  · 事件類(lèi)型,布爾值,這個(gè)必須和注冊事件時(shí)的類(lèi)型一致。

  也就是說(shuō),名稱(chēng)、回調、類(lèi)型,三者共同決定解除哪個(gè)事件,缺一不可。舉個(gè)例子:

  復制代碼 代碼如下:

  var btn = document.getElementById("test");

  //將回調存儲在變量中

  var fn = function(e){

  alert("ok");

  };

  //綁定

  btn.addEventListener("click", fn, false);

  //解除

  btn.removeEventListener("click", fn, false);

  要想注冊過(guò)的事件能夠被解除,必須將回調函數保存起來(lái),否則無(wú)法解除。

  DOM0與DOM2混用

  事情本來(lái)就很亂了,這又來(lái)個(gè)混合使用,還讓不讓人活了。。。

  別怕,混合使用完全沒(méi)問(wèn)題,DOM0模型和DOM2模型各自遵循自己的規則,互不影響。

  整體上來(lái)說(shuō),依然是哪個(gè)先注冊,哪個(gè)先執行,其他就沒(méi)什么了。

  后記

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

  在實(shí)際應用中,真正的行家不會(huì )傻傻的真的注冊這么多事件,一般情況下,只需在最外層dom元素注冊一次事件,然后通過(guò)捕獲、冒泡機制去找到真正觸發(fā)事件的dom元素,最后根據觸發(fā)事件的dom元素提供的信息去調用回調。

  也就是說(shuō),行家會(huì )自己管理事件,而不依賴(lài)瀏覽器去管理,這樣即可以提高效率,又保證了兼容性,JQuery不就是這么做的嘛~

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

【深入分析原生JavaScript事件分析】相關(guān)文章:

Javascript函數的定義和用法分析08-15

javascript分析運算符用法08-07

工程碩士gct考試邏輯考試深入分析01-11

javascript閉包的定義及應用實(shí)例分析08-25

Javascript 閉包引起IE內存泄露分析07-05

對javascript的理解08-08

常用的JavaScript模式09-22

Javascript的this用法簡(jiǎn)述08-15

JavaScript學(xué)習筆記08-24

JavaScript 基礎教學(xué)09-29

激情欧美日韩一区二区,浪货撅高贱屁股求主人调教视频,精品无码成人片一区二区98,国产高清av在线播放,色翁荡息又大又硬又粗视频