日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【转】理解JavaScript中的事件处理

發(fā)布時(shí)間:2024/8/23 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】理解JavaScript中的事件处理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

? 這篇文章對(duì)于了解Javascript的事件處理機(jī)制非常好,將它全文轉(zhuǎn)載于此,以備不時(shí)之需。

? 轉(zhuǎn)載地址:http://www.cnblogs.com/binyong/articles/1750263.html?感謝作者!

?

什么是事件?

事件(Event)是JavaScript應(yīng)用跳動(dòng)的心臟 ,也是把所有東西粘在一起的膠水。當(dāng)我們與瀏覽器中 Web 頁(yè)面進(jìn)行某些類(lèi)型的交互時(shí),事件就發(fā)生了。事件可能是用戶(hù)在某些內(nèi)容上的點(diǎn)擊、鼠標(biāo)經(jīng)過(guò)某個(gè)特定元素或按下鍵盤(pán)上的某些按鍵。事件還可能是 Web 瀏覽器中發(fā)生的事情,比如說(shuō)某個(gè) Web 頁(yè)面加載完成,或者是用戶(hù)滾動(dòng)窗口或改變窗口大小。

通過(guò)使用 JavaScript ,你可以監(jiān)聽(tīng)特定事件的發(fā)生,并規(guī)定讓某些事件發(fā)生以對(duì)這些事件做出響應(yīng)。

今天的事件

在漫長(zhǎng)的演變史,我們已經(jīng)告別了內(nèi)嵌式的事件處理方式(直接將事件處理器放在 HTML 元素之內(nèi)來(lái)使用)。今天的事件,它已是DOM的重要組成部分,遺憾的是, IE繼續(xù)保留它最早在IE4.0中實(shí)現(xiàn)的事件模型,以后的IE版本中也沒(méi)有做太大的改變,這也就是說(shuō)IE還是使用的是一種專(zhuān)有的事件模型(冒泡型),而其它的主流瀏覽器直到DOM 級(jí)別 3 規(guī)定定案后,才陸陸續(xù)續(xù)支持DOM標(biāo)準(zhǔn)的事件處理模型 — 捕獲型與冒泡型。

歷史原因是:W3C 規(guī)范 在DOM 級(jí)別 1中并沒(méi)有定義任何的事件,直到發(fā)布于 2000 年 11 月 的DOM 級(jí)別 2 才定義了一小部分子集,DOM 級(jí)別 2中已經(jīng)提供了提供了一種更詳細(xì)的更細(xì)致的方式以控制 Web 頁(yè)面中的事件,最后,完整的事件是在2004年 DOM 級(jí)別 3的規(guī)定中才最終定案。因?yàn)镮E4是1995推出的并已實(shí)現(xiàn)了自己的事件模型(冒泡型),當(dāng)時(shí)根本就沒(méi)有DOM標(biāo)準(zhǔn),不過(guò)在以后的DOM標(biāo)準(zhǔn)規(guī)范過(guò)程中已經(jīng)把IE的事件模型吸收到了其中。

目前除IE瀏覽器外,其它主流的Firefox, Opera,
Safari都支持標(biāo)準(zhǔn)的DOM事件處理模型。IE仍然使用自己專(zhuān)有的事件模型,即冒泡型,它事件模型的一部份被DOM標(biāo)準(zhǔn)采用,這點(diǎn)對(duì)于開(kāi)發(fā)者來(lái)說(shuō)也是有好處的,只有使用
DOM標(biāo)準(zhǔn),IE都共有的事件處理方式才能有效的跨瀏覽器。

DOM事件流

DOM(文檔對(duì)象模型)結(jié)構(gòu)是一個(gè)樹(shù)型結(jié)構(gòu),當(dāng)一個(gè)HTML元素產(chǎn)生一個(gè)事件時(shí),該事件會(huì)在元素結(jié)點(diǎn)與根節(jié)點(diǎn)之間按特定的順序傳播,路徑所經(jīng)過(guò)的節(jié)點(diǎn)都會(huì)收到該事件,這個(gè)傳播過(guò)程可稱(chēng)為DOM事件流。

事件順序有兩種類(lèi)型:事件捕捉事件冒泡

冒泡型事件(Event Bubbling)

這是IE瀏覽器對(duì)事件模型的實(shí)現(xiàn),也是最容易理解的,至少筆者覺(jué)得比較符合實(shí)際的。冒泡,顧名思義,事件像個(gè)水中的氣泡一樣一直往上冒,直到頂端。從
DOM樹(shù)型結(jié)構(gòu)上理解,就是事件由葉子節(jié)點(diǎn)沿祖先結(jié)點(diǎn)一直向上傳遞直到根節(jié)點(diǎn);從瀏覽器界面視圖HTML元素排列層次上理解就是事件由具有從屬關(guān)系的最確定的目標(biāo)元素一直傳遞到最不確定的目標(biāo)元素.冒泡技術(shù).冒泡型事件的基本思想,事件按照從特定的事件目標(biāo)開(kāi)始到最不確定的事件目標(biāo).

捕獲型事件(Event Capturing)

Netscape 的實(shí)現(xiàn),它與冒泡型剛好相反,由DOM樹(shù)最頂層元素一直到最精確的元素,這個(gè)事件模型對(duì)于開(kāi)發(fā)者來(lái)說(shuō)(至少是我..)有點(diǎn)費(fèi)解,因?yàn)橹庇^上的理解應(yīng)該如同冒泡型,事件傳遞應(yīng)該由最確定的元素,即事件產(chǎn)生元素開(kāi)始。

?

DOM標(biāo)準(zhǔn)的事件模型

我們已經(jīng)對(duì)上面兩個(gè)不同的事件模型進(jìn)行了解釋和對(duì)比。DOM標(biāo)準(zhǔn)同時(shí)支持兩種事件模型,即捕獲型事件冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流都會(huì)觸發(fā)DOM中的所有對(duì)象,從document對(duì)象開(kāi)始,也在document對(duì)象結(jié)束(大部分兼容標(biāo)準(zhǔn)的瀏覽器會(huì)繼續(xù)將事件是捕捉/冒泡延續(xù)到window對(duì)象)。

如圖:首先是捕獲式傳遞事件,接著是冒泡式傳遞,所以,如果一個(gè)處理函數(shù)既注冊(cè)了捕獲型事件的監(jiān)聽(tīng),又注冊(cè)冒泡型事件監(jiān)聽(tīng),那么在DOM事件模型中它就會(huì)被調(diào)用兩次。

DOM標(biāo)準(zhǔn)的事件模型最獨(dú)特的性質(zhì)是,文本節(jié)點(diǎn)也會(huì)觸發(fā)事件(在IE不會(huì))。

事件傳送

為了更好的說(shuō)明DOM標(biāo)準(zhǔn)中的事件流原理,我們把它放在“事件傳送”小結(jié)里來(lái)更具體的解釋。

顯然,如果為一個(gè)超鏈接添加了click事件監(jiān)聽(tīng)器,那么當(dāng)該鏈接被點(diǎn)擊時(shí)該事件監(jiān)聽(tīng)器就會(huì)被執(zhí)行。但如果把該事件監(jiān)聽(tīng)器指派給了包含該鏈接的p元素或者位于DOM樹(shù)頂端的document節(jié)點(diǎn),那么點(diǎn)擊該鏈接也同樣會(huì)觸發(fā)該事件監(jiān)聽(tīng)器。這是因?yàn)槭录粌H僅對(duì)觸發(fā)的目標(biāo)元素產(chǎn)生影響,它們還會(huì)對(duì)沿著DOM結(jié)構(gòu)的所有元素產(chǎn)生影響。這就是大家所熟悉的事件轉(zhuǎn)送

W3C事件模型中明確地指出了事件轉(zhuǎn)送的原理。事件傳送可以分為3個(gè)階段。

如圖:標(biāo)準(zhǔn)的事件轉(zhuǎn)送模式

(1).在事件捕捉(Capturing)階段,事件將沿著DOM樹(shù)向下轉(zhuǎn)送,目標(biāo)節(jié)點(diǎn)的每一個(gè)祖先節(jié)點(diǎn),直至目標(biāo)節(jié)點(diǎn)。例如,若用戶(hù)單擊了一個(gè)超鏈接,則該單擊事件將從document節(jié)點(diǎn)轉(zhuǎn)送到html元素,body元素以及包含該鏈接的p元素。

在此過(guò)程中,瀏覽器都會(huì)檢測(cè)針對(duì)該事件的捕捉事件監(jiān)聽(tīng)器,并且運(yùn)行這件事件監(jiān)聽(tīng)器。

(2). 在目標(biāo)(target)階段,瀏覽器在查找到已經(jīng)指定給目標(biāo)事件的事件監(jiān)聽(tīng)器之后,就會(huì)運(yùn)行 該事件監(jiān)聽(tīng)器。目標(biāo)節(jié)點(diǎn)就是觸發(fā)事件的DOM節(jié)點(diǎn)。例如,如果用戶(hù)單擊一個(gè)超鏈接,那么該鏈接就是目標(biāo)節(jié)點(diǎn)(此時(shí)的目標(biāo)節(jié)點(diǎn)實(shí)際上是超鏈接內(nèi)的文本節(jié)點(diǎn))。

(3).在冒泡(Bubbling)階段,事件將沿著DOM樹(shù)向上轉(zhuǎn)送,再次逐個(gè)訪問(wèn)目標(biāo)元素的祖先節(jié)點(diǎn)到document節(jié)點(diǎn)。該過(guò)程中的每一步。瀏覽器都將檢測(cè)那些不是捕捉事件監(jiān)聽(tīng)器的事件監(jiān)聽(tīng)器,并執(zhí)行它們。

并非所有的事件都會(huì)經(jīng)過(guò)冒泡階段的

所有的事件都要經(jīng)過(guò)捕捉階段和目標(biāo)階段,但是有些事件會(huì)跳過(guò)冒泡階段。例如,讓元素獲得輸入焦點(diǎn)的focus事件以及失去輸入焦點(diǎn)的blur事件就都不會(huì)冒泡。

?

事件句柄和事件接聽(tīng)器

事件句柄

事件句柄(又稱(chēng)事件處理函數(shù),DOM稱(chēng)之為事件監(jiān)聽(tīng)函數(shù)),用于響應(yīng)某個(gè)事件而調(diào)用的函數(shù)稱(chēng)為事件處理函數(shù)
。每一個(gè)事件均對(duì)應(yīng)一個(gè)事件句柄,在程序執(zhí)行時(shí),將相應(yīng)的函數(shù)或語(yǔ)句指定給事件句柄,則在該事件發(fā)生時(shí),瀏覽器便執(zhí)行指定的函數(shù)或語(yǔ)句,從而實(shí)現(xiàn)網(wǎng)頁(yè)內(nèi)容與用戶(hù)操作的交互。當(dāng)瀏覽器檢測(cè)到某事件發(fā)生時(shí),便查找該事件對(duì)應(yīng)的事件句柄有沒(méi)有被賦值,如果有,則執(zhí)行該事件句柄。

我們認(rèn)為響應(yīng)點(diǎn)擊事件的函數(shù)是onclick事件處理函數(shù)。以前,事件處理函數(shù)有兩種分配方式:在JavaScript中或者在HTML中

如果在JavaScript 中分配事件處理函數(shù), 則需要首先獲得要處理的對(duì)象的一引用,然后將函數(shù)賦值給對(duì)應(yīng)的事件處理函數(shù)屬性,請(qǐng)看一個(gè)簡(jiǎn)單的例子:

?

1?var?link=document.getElementById("mylink");
2?link.οnclick=function(){
3???alert("I?was?clicked?!");
4?};?

?

從我們看到的例子中,我們發(fā)現(xiàn)使用事件句柄很容易,
不過(guò)事件處理函數(shù)名稱(chēng)必須是小寫(xiě)的,還有就是只有在
元素載入完成之后才能將事件句柄賦給元素,不然會(huì)有異常。

關(guān)于文檔載入技術(shù),請(qǐng)看《window.onload加載的多種解決方案》?的文章。

如果在HTML中分配事件句柄的話,則直接通過(guò)HTML屬性來(lái)設(shè)置事件處理函數(shù)就行了,并在其中包含合適的腳本作為特性值就可以了,例如:

<a href="/" οnclick="JavaScript code here">......</a>

這種JavaScript 代碼和通過(guò)HTML的style屬性直接將CSS屬性賦給元素類(lèi)似。這樣會(huì)代碼看起來(lái)一團(tuán)糟,也違背了將實(shí)現(xiàn)動(dòng)態(tài)行為的代碼與顯示文檔靜態(tài)內(nèi)容的代碼相分離的原則。從1998年開(kāi)始,這種寫(xiě)法就過(guò)時(shí)了。

這種傳統(tǒng)的事件綁定技術(shù),優(yōu)缺點(diǎn)是顯然的:

*簡(jiǎn)單方便,在HTML中直接書(shū)寫(xiě)處理函數(shù)的代碼塊,在JS中給元素對(duì)應(yīng)事件屬性賦值即可。

*IE與DOM標(biāo)準(zhǔn)都支持的一種方法,它在IE與DOM標(biāo)準(zhǔn)中都是在事件冒泡過(guò)程中被調(diào)用的。

*可以在處理函數(shù)塊內(nèi)直接用this引用注冊(cè)事件的元素,this引用的是當(dāng)前元素。

*要給元素注冊(cè)多個(gè)監(jiān)聽(tīng)器,就不能用這方法了。

事件接聽(tīng)器

除了前面已經(jīng)介紹的簡(jiǎn)單事件句柄之外,現(xiàn)在大多數(shù)瀏覽器都內(nèi)置了一些更高級(jí)的事件處理方式,即,事件監(jiān)聽(tīng)器,這種處理方式就不受一個(gè)元素只能綁定一個(gè)事件句柄的限制。

我們已經(jīng)知道了事件句柄與事件監(jiān)聽(tīng)器的最大不同之處是使用事件句柄時(shí)一次只能插接一個(gè)事件句柄,但對(duì)于事件監(jiān)聽(tīng)器,一次可以插接多個(gè)。

IE下的事件監(jiān)聽(tīng)器:

IE提供的卻是一種自有的,完全不同的甚至存在BUG的事件監(jiān)聽(tīng)器,因此如果要讓腳本在本瀏覽器中正常運(yùn)行的話,就必須使用IE所支持的事件監(jiān)聽(tīng)器。另外,Safari 瀏覽器中的事件監(jiān)聽(tīng)器有時(shí)也存在一點(diǎn)不同。

在IE中,每個(gè)元素和window對(duì)象都有兩個(gè)方法:attachEvent方法和detachEvent方法。?

1?element.attachEvent("onevent",eventListener);

此方法的意思是在IE中要想給一個(gè)元素的事件附加事件處理函數(shù),必須調(diào)用attachEvent方法才能創(chuàng)建一個(gè)事件監(jiān)聽(tīng)器。attachEvent方法允許外界注冊(cè)該元素多個(gè)事件監(jiān)聽(tīng)器。

attachEvent接受兩個(gè)參數(shù)。第一個(gè)參數(shù)是事件類(lèi)型名,第二個(gè)參數(shù)eventListener是回調(diào)處理函數(shù)。這里得說(shuō)明一下,有個(gè)經(jīng)常會(huì)出錯(cuò)的地方,IE下
利用attachEvent注冊(cè)的處理函數(shù)調(diào)用時(shí)this指向不再是先前注冊(cè)事件的元素,這時(shí)的this為window對(duì)象。還有一點(diǎn)是此方法的事件類(lèi)型名稱(chēng)必須加上一個(gè)”on”的前綴(如onclick)。?

1?element.attachEvent("onevent",eventListener);

要想移除先前元素注冊(cè)的事件監(jiān)聽(tīng)器,可以使用detachEvent方法進(jìn)行刪除,參數(shù)相同。

DOM標(biāo)準(zhǔn)下的事件監(jiān)聽(tīng)器:

在支持W3C標(biāo)準(zhǔn)事件監(jiān)聽(tīng)器的瀏覽器中,對(duì)每個(gè)支持事件的對(duì)象都可以使用addEventListener方法。該方法既支持注冊(cè)冒泡型事件處理,又支持捕獲型事件處理。所以與IE瀏覽器中注冊(cè)元素事件監(jiān)聽(tīng)器方式有所不同的。

1?//標(biāo)準(zhǔn)語(yǔ)法?
2?element.addEventListener('event',?eventListener,?useCapture);
3?//默認(rèn)
4?element.addEventListener('event',?eventListener,?false);

addEventListener方法接受三個(gè)參數(shù)。第一個(gè)參數(shù)是事件類(lèi)型名,值得注意的是,這里事件類(lèi)型名稱(chēng)與IE的不同,事件類(lèi)型名是沒(méi)’on’開(kāi)頭的;第二個(gè)參數(shù)eventListener是回調(diào)處理函數(shù)(即監(jiān)聽(tīng)器函數(shù));第三個(gè)參數(shù)注明該處理回調(diào)函數(shù)是在事件傳遞過(guò)程中的捕獲階段被調(diào)用還是冒泡階段被調(diào)用 ,通常此參數(shù)通常會(huì)設(shè)置為false(為false時(shí)是冒泡),那么,如果將其值設(shè)置為true,那就創(chuàng)建一個(gè)捕捉事件監(jiān)聽(tīng)器。

移除已注冊(cè)的事件監(jiān)聽(tīng)器調(diào)用element的removeEventListener方法即可,參數(shù)相同。

1?//標(biāo)準(zhǔn)語(yǔ)法?
2?element.removeEventListener('event',?eventListener,?useCapture);
3?//默認(rèn)
4?element.removeEventListener('event',?eventListener,?false);

通過(guò)addEventListener方法添加的事件處理函數(shù),必須使用removeEventListener方法才能刪除,而且要求參數(shù)與添加事件處理函數(shù)時(shí)addEventListener方法的參數(shù)完全一致(包括useCapture參數(shù)),否則將不能成功刪除事件處理函數(shù)。

跨瀏覽器的注冊(cè)與移除元素事件監(jiān)聽(tīng)器方案

我們現(xiàn)在已經(jīng)知道,對(duì)于支持addEventListener方法的瀏覽器,只要需要事件監(jiān)聽(tīng)器腳本就都需要調(diào)用addEventListener方法;而對(duì)于不支持該方法的IE瀏覽器,使用事件監(jiān)聽(tīng)器時(shí)則需要調(diào)用attachEvent方法。要確保瀏覽器使用正確的方法其實(shí)并不困難,只需要通過(guò)一個(gè)if-else語(yǔ)句來(lái)檢測(cè)當(dāng)前瀏覽器中是否存在addEventListener方法或attachEvent方法即可。

這樣的方式就可以實(shí)現(xiàn)一個(gè)跨瀏覽器的注冊(cè)與移除元素事件監(jiān)聽(tīng)器方案:

?

1?var?EventUtil?=?{
?2???//注冊(cè)
?3???addHandler:?function(element,?type,?handler){
?4?????if?(element.addEventListener){
?5???????element.addEventListener(type,?handler,?false);
?6?????}?else?if?(element.attachEvent){
?7???????element.attachEvent("on"?+?type,?handler);
?8?????}?else?{
?9???????element["on"?+?type]?=?handler;
10?????}
11???},
12???//移除注冊(cè)
13???removeHandler:?function(element,?type,?handler){
14?????if?(element.removeEventListener){
15?????????????element.removeEventListener(type,?handler,?false);
16?????}?else?if?(element.detachEvent){
17?????????????element.detachEvent("on"?+?type,?handler);
18?????}?else?{
19?????????????element["on"?+?type]?=?null;
20?????}
21???}?????????????
22??};?

?

事件對(duì)象引用

為了更好的處理事件,你可以根據(jù)所發(fā)生的事件的特定屬性來(lái)采取不同的操作。

如事件模型一樣,IE 和其他瀏覽器處理方法不同:IE 使用一個(gè)叫做 event 的全局事件對(duì)象來(lái)處理對(duì)象(它可以在全局變量window.event中找到),而其它所有瀏覽器采用的 W3C 推薦的方式,則使用獨(dú)立的包含事件對(duì)象的參數(shù)傳遞。

跨瀏覽器實(shí)現(xiàn)這樣的功能時(shí),最常見(jiàn)的問(wèn)題就是獲取事件本身的引用及獲取該事件的目標(biāo)元素的引用。

下面這段代碼就為你解決了這個(gè)問(wèn)題:

1?var?EventUtil?={
2???getEvent:?function(event){
3?????return?event???event?:?window.event;
4???},
5???getTarget:?function(event){
6?????return?event.target?||?event.srcElement;
7???}
8?};

?

停止事件冒泡和阻止事件的默認(rèn)行為

“停止事件冒泡“和”阻止瀏覽器的默認(rèn)行為“,這兩個(gè)概念非常重要,它們對(duì)復(fù)雜的應(yīng)用程序處理非常有用。

1.停止事件冒泡

停止事件冒泡是指,停止冒泡型事件的進(jìn)一步傳遞(取消事件傳遞,不只是停止IE和DOM標(biāo)準(zhǔn)共有的冒泡型事件,我們還可以停止支持DOM標(biāo)準(zhǔn)瀏覽器的捕捉型事件,用topPropagation()方法)。例如上圖中的冒泡型事件傳遞中,在body處理停止事件傳遞后,位于上層的document的事件監(jiān)聽(tīng)器就不再收到通知,不再被處理。

2.阻止事件的默認(rèn)行為

停止事件的默認(rèn)行為是指,通常瀏覽器在事件傳遞并處理完后會(huì)執(zhí)行與該事件關(guān)聯(lián)的默認(rèn)動(dòng)作(如果存在這樣的動(dòng)作)。例如,如果表單中input type 屬性是 “submit”,點(diǎn)擊后在事件傳播完瀏覽器就自動(dòng)提交表單。又例如,input 元素的 keydown 事件發(fā)生并處理后,瀏覽器默認(rèn)會(huì)將用戶(hù)鍵入的字符自動(dòng)追加到 input 元素的值中。

停止事件冒泡的處理方法

在IE下,通過(guò)設(shè)置event對(duì)象的cancelBubble為true即可。

1?function?someHandle()?{
2???window.event.cancelBubble?=?true;
3?}

DOM標(biāo)準(zhǔn)通過(guò)調(diào)用event對(duì)象的stopPropagation()方法即可。

1?function?someHandle(event)?{
2???event.stopPropagation();
3?}

因些,跨瀏覽器的停止事件傳遞的方法是:

1?function?someHandle(event)?{
2???event?=?event?||?window.event;
3???if(event.stopPropagation){
4?????event.stopPropagation();
5???}else?{
6?????event.cancelBubble?=?true;
7???}
8?}

?

阻止事件的默認(rèn)行為的處理方法

就像事件模型和事件對(duì)象差異一樣,在IE和其它所有瀏覽器中阻止事件的默認(rèn)行為的方法也不同。

在IE下,通過(guò)設(shè)置event對(duì)象的returnValue為false即可。

1?function?someHandle()?{
2???window.event.returnValue?=?false;
3?}

DOM標(biāo)準(zhǔn)通過(guò)調(diào)用event對(duì)象的preventDefault()方法即可。

1?function?someHandle(event)?{
2???event.preventDefault();
3?}

因些,跨瀏覽器的取消事件傳遞后的默認(rèn)處理方法是:

1?function?someHandle(event)?{
2???event?=?event?||?window.event;
3???if(event.preventDefault){
4?????event.preventDefault();
5???}else{
6?????event.returnValue?=?false;
7???}
8?}

完整的事件處理兼容性函數(shù)?

1?var?EventUtil?=?{
?2???addHandler:?function(element,?type,?handler){
?3?????if?(element.addEventListener){
?4???????element.addEventListener(type,?handler,?false);
?5?????}?else?if?(element.attachEvent){
?6???????element.attachEvent("on"?+?type,?handler);
?7?????}?else?{
?8???????element["on"?+?type]?=?handler;
?9?????}
10???},
11???removeHandler:?function(element,?type,?handler){
12?????if?(element.removeEventListener){
13???????element.removeEventListener(type,?handler,?false);
14?????}?else?if?(element.detachEvent){
15???????element.detachEvent("on"?+?type,?handler);
16?????}?else?{
17???????element["on"?+?type]?=?null;
18?????}
19???},
20???getEvent:?function(event){
21?????return?event???event?:?window.event;
22???},
23???getTarget:?function(event){
24?????return?event.target?||?event.srcElement;
25???},
26???preventDefault:?function(event){
27?????if?(event.preventDefault){
28???????event.preventDefault();
29?????}?else?{
30???????event.returnValue?=?false;
31?????}
32???},
33???stopPropagation:?function(event){
34?????if?(event.stopPropagation){
35???????event.stopPropagation();
36?????}?else?{
37???????event.cancelBubble?=?true;
38?????}
39?};

?

捕獲型事件模型與冒泡型事件模型的應(yīng)用場(chǎng)合

標(biāo)準(zhǔn)事件模型為我們提供了兩種方案,可能很多朋友分不清這兩種不同模型有啥好處,為什么不只采取一種模型。
這里拋開(kāi)IE瀏覽器討論(IE只有一種,沒(méi)法選擇)什么情況下適合哪種事件模型。

1. 捕獲型應(yīng)用場(chǎng)合

捕獲型事件傳遞由最不精確的祖先元素一直到最精確的事件源元素,傳遞方式與操作系統(tǒng)中的全局快捷鍵與應(yīng)用程序快捷鍵相似。當(dāng)一個(gè)系統(tǒng)組合鍵發(fā)生時(shí),如果注
冊(cè)了系統(tǒng)全局快捷鍵監(jiān)聽(tīng)器,該事件就先被操作系統(tǒng)層捕獲,全局監(jiān)聽(tīng)器就先于應(yīng)用程序快捷鍵監(jiān)聽(tīng)器得到通知,也就是全局的先獲得控制權(quán),它有權(quán)阻止事件的進(jìn)
一步傳遞。所以捕獲型事件模型適用于作全局范圍內(nèi)的監(jiān)聽(tīng),這里的全局是相對(duì)的全局,相對(duì)于某個(gè)頂層結(jié)點(diǎn)與該結(jié)點(diǎn)所有子孫結(jié)點(diǎn)形成的集合范圍。

例如你想作全局的點(diǎn)擊事件監(jiān)聽(tīng),相對(duì)于document結(jié)點(diǎn)與document下所有的子結(jié)點(diǎn),在某個(gè)條件下要求所有的子結(jié)點(diǎn)點(diǎn)擊無(wú)效,這種情況下冒泡模型就解決不了了,而捕獲型卻非常適合,可以在最頂層結(jié)點(diǎn)添加捕獲型事件監(jiān)聽(tīng)器,偽碼如下:

1?function?globalClickListener(event)?{
2???if(canEventPass?==?false)?{
3?????//取消事件進(jìn)一步向子結(jié)點(diǎn)傳遞和冒泡傳遞
4?????event.stopPropagation();
5?????//取消瀏覽器事件后的默認(rèn)執(zhí)行
6?????event.preventDefault();
7???}
8?}

這樣一來(lái),當(dāng)canEventPass條件為假時(shí),document下所有的子結(jié)點(diǎn)click注冊(cè)事件都不會(huì)被瀏覽器處理。

2. 冒泡型的應(yīng)用場(chǎng)合

可以說(shuō)我們平時(shí)用的都是冒泡事件模型,因?yàn)镮E只支持這模型。這里還是說(shuō)說(shuō),在恰當(dāng)利用該模型可以提高腳本性能。在元素一些頻繁觸發(fā)的事件中,如
onmousemove,
onmouseover,onmouseout,如果明確事件處理后沒(méi)必要進(jìn)一步傳遞,那么就可以大膽的取消它。此外,對(duì)于子結(jié)點(diǎn)事件監(jiān)聽(tīng)器的處理會(huì)對(duì)父
層監(jiān)聽(tīng)器處理造成負(fù)面影響的,也應(yīng)該在子結(jié)點(diǎn)監(jiān)聽(tīng)器中禁止事件進(jìn)一步向上傳遞以消除影響。

綜合案例分析

最后結(jié)合下面HTML代碼作分析:

1?<body?οnclick="alert('current?is?body');">
?2???<div?id="div0"?οnclick="alert('current?is?'+this.id)">
?3?????<div?id="div1"?οnclick="alert('current?is?'+this.id)">
?4???????<div?id="div2"?οnclick="alert('current?is?'+this.id)">
?5?????????<div?id="event_source"?οnclick="alert('current?is?'+this.id)"?style="height:200px;width:200px;background-color:red;"></div>
?6???????</div>
?7?????</div>
?8???</div>
?9?</body>
10?

HTML運(yùn)行后點(diǎn)擊紅色區(qū)域,這是最里層的DIV,根據(jù)上面說(shuō)明,無(wú)論是DOM標(biāo)準(zhǔn)還是IE,直接寫(xiě)在html里的監(jiān)聽(tīng)處理函數(shù)是事件冒泡傳遞時(shí)調(diào)用的,由最里層一直往上傳遞,所以會(huì)先后出現(xiàn)
current is event_source
current is div2
current is div1
current is div0
current is body

添加以下片段:

1?var?div2?=?document.getElementById('div2');
2?EventUtil.addHandler(div2,?'click',?function(event){
3???event?=?EventUtil.getEvent(event);
4???EventUtil.stopPropagation(event);
5?},?false);

current is event_sourcecurrent is div2

當(dāng)點(diǎn)擊紅色區(qū)域后,根據(jù)上面說(shuō)明,在泡冒泡處理期間,事件傳遞到div2后被停止傳遞了,所以div2上層的元素收不到通知,所以會(huì)先后出現(xiàn):

在支持DOM標(biāo)準(zhǔn)的瀏覽器中,添加以下代碼:

1?document.body.addEventListener('click',?function(event){
2???event.stopPropagation();
3?},?true);

以上代碼中的監(jiān)聽(tīng)函數(shù)由于是捕獲型傳遞時(shí)被調(diào)用的,所以點(diǎn)擊紅色區(qū)域后,雖然事件源是ID為event_source的元素,但捕獲型選傳遞,從最頂層開(kāi)始,body結(jié)點(diǎn)監(jiān)聽(tīng)函數(shù)先被調(diào)用,并且取消了事件進(jìn)一步向下傳遞,所以只會(huì)出現(xiàn) current is body .

轉(zhuǎn)載于:https://www.cnblogs.com/xmmcn/archive/2012/11/07/2758942.html

總結(jié)

以上是生活随笔為你收集整理的【转】理解JavaScript中的事件处理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。