国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

原生JavaScript事件詳解

_ang / 3161人閱讀

摘要:事件通過和管理,當(dāng)然,這是標(biāo)準(zhǔn)。最后一個參數(shù)是布爾型,代表捕獲事件,代表冒泡事件。事件類型,布爾值,這個必須和注冊事件時的類型一致。也就是說,名稱回調(diào)類型,三者共同決定解除哪個事件,缺一不可。

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

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

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

DOM0事件模型

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

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

直接在dom對象上注冊事件名稱,就是DOM0寫法,比如:

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

意思就是注冊一個onclick事件。當(dāng)然,它和這種寫法是一個意思:

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

這沒什么,只不過是兩種訪問js對象屬性的方法,[]的形式主要是為了解決屬性名不是合法的標(biāo)識符,比如:object.123肯定報錯,但是object["123"]就避免了這個問題,與此同時,[]的寫法,也把js寫活了,用字符串表示屬性名稱,可以在運行時動態(tài)綁定事件。

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

基于DOM0的事件,對于同一個dom節(jié)點而言,只能注冊一個,后邊注冊的同種事件會覆蓋之前注冊的。例如:

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

btn.onmousemove = function(e){
  alert("ok");
};

 btn["onmousemove"] = function(e){
  alert("ok1");
};

結(jié)果會輸出ok1。

接下來再說說this。事件觸發(fā)時,this就是指該事件在哪個dom對象上觸發(fā)。例如:

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

btn.onmousemove = function(e){
  alert(this.id);
};

結(jié)果輸出test。因為事件就是在id為test的dom節(jié)點上注冊的,事件觸發(fā)時,this當(dāng)然代表這個dom節(jié)點,可以理解為事件是被這個dom節(jié)點調(diào)用的。

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

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

btn.onclick = function(e){
  alert("ok");
};

 btn.onclick = null;

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

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

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

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

DOM2事件模型

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

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

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

DOM2事件通過addEventListener和removeEventListener管理,當(dāng)然,這是標(biāo)準(zhǔn)。

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

addEventListener當(dāng)然就是注冊事件,她有三個參數(shù),分別為:"事件名稱", "事件回調(diào)", "捕獲/冒泡"。舉個例子:

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

btn.addEventListener("click", function(e){
  alert("ok");
}, false);

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

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

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

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

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

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

假設(shè)有這樣的html結(jié)構(gòu):

然后我們在外層div上注冊兩個click事件,分別是捕獲事件和冒泡事件,代碼如下:

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

//捕獲事件
btn.addEventListener("click", function(e){
  alert("ok1");
 }, true);

//冒泡事件
btn.addEventListener("click", function(e){
  alert("ok");

1 }, false);

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

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

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

html結(jié)構(gòu)同上,js代碼如下:

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

//冒泡事件
btnInner.addEventListener("click", function(e){
  alert("ok");
 }, false);

//捕獲事件
btnInner.addEventListener("click", function(e){
  alert("ok1");

1 }, true);

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

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

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

btnInner.addEventListener("click", function(e){
  alert("ok");
}, false);

 btnInner.addEventListener("click", function(e){
  alert("ok1");
}, false);

1 btnInner.addEventListener("click", function(e){
1 alert("ok2");
1 }, false);

結(jié)果當(dāng)然是依次彈出ok、ok1、ok2。

為了進一步理解事件模型,還有一種場景,假如說外層div和內(nèi)層div同時注冊了捕獲事件,那么點擊內(nèi)層div時,外層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);

結(jié)果是先彈出ok1。

假如外層div和內(nèi)層div都是注冊的冒泡事件,點擊內(nèi)層div時,一定是內(nèi)層div事件先執(zhí)行,原理相同。

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

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

其實,事件觸發(fā)時,會默認(rèn)傳入一個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("事件名稱", "事件回調(diào)", "捕獲/冒泡");

這和綁定事件的參數(shù)一樣,詳細(xì)說明下:

· 事件名稱,就是說解除哪個事件唄。

· 事件回調(diào),是一個函數(shù),這個函數(shù)必須和注冊事件的函數(shù)是同一個。

· 事件類型,布爾值,這個必須和注冊事件時的類型一致。

也就是說,名稱、回調(diào)、類型,三者共同決定解除哪個事件,缺一不可。舉個例子:

var btn = document.getElementById("test");
//將回調(diào)存儲在變量中
var fn = function(e){
  alert("ok");
};
 //綁定
 btn.addEventListener("click", fn, false);

//解除
btn.removeEventListener("click", fn, false);

要想注冊過的事件能夠被解除,必須將回調(diào)函數(shù)保存起來,否則無法解除。

DOM0與DOM2混用

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

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

整體上來說,依然是哪個先注冊,哪個先執(zhí)行,其他就沒什么了。

后記

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

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

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

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

手抽筋中。。。

(轉(zhuǎn)自 楊元)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87680.html

相關(guān)文章

  • 【連載】前端個人文章整理-從基礎(chǔ)到入門

    摘要:個人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時間了,由于工作比較忙,更新緩慢,后面還是會繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個人前端文章整理 從最開始萌生寫文章的想法,到著手...

    madthumb 評論0 收藏0
  • 5、React組件事件詳解

    摘要:組件事件響應(yīng)在構(gòu)建虛擬的同時,還構(gòu)建了自己的事件系統(tǒng)且所有事件對象和規(guī)范保持一致。的事件系統(tǒng)和瀏覽器事件系統(tǒng)相比,主要增加了兩個特性事件代理和事件自動綁定。 React組件事件響應(yīng) React在構(gòu)建虛擬DOM的同時,還構(gòu)建了自己的事件系統(tǒng);且所有事件對象和W3C規(guī)范保持一致。 React的事件系統(tǒng)和瀏覽器事件系統(tǒng)相比,主要增加了兩個特性:事件代理、和事件自動綁定。 1、事件代理 ...

    Ververica 評論0 收藏0
  • 詳解vue組件三大核心概念

    摘要:前言本文主要介紹屬性事件和插槽這三個基礎(chǔ)概念使用方法及其容易被忽略的一些重要細(xì)節(jié)。至于如何改變,我們接下去詳細(xì)介紹單向數(shù)據(jù)流這個概念出現(xiàn)在組件通信。比如上例中在子組件中修改父組件傳遞過來的數(shù)組從而改變父組件的狀態(tài)。的一個核心思想是數(shù)據(jù)驅(qū)動。 前言 本文主要介紹屬性、事件和插槽這三個vue基礎(chǔ)概念、使用方法及其容易被忽略的一些重要細(xì)節(jié)。如果你閱讀別人寫的組件,也可以從這三個部分展開,它們...

    rickchen 評論0 收藏0
  • JavaScript系列之事件詳解

    摘要:響應(yīng)某個事件的函數(shù)就叫事件處理程序或事件偵聽器。為事件指定事件處理程序的方法主要有種。事件處理程序事件直接加在元素上。事件委托利用冒泡的原理,把事件加到父元素或祖先元素上,觸發(fā)執(zhí)行效果,解決事件處理程序過多問題。事件委托優(yōu)點提高性能。 JavaScript簡單入門可以看看我丑丑的Github博客JavaScript簡單入門 事件 JavaScript與HTML之間的交互是通過事件實現(xiàn)的...

    pakolagij 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<