国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

關于DOM事件模型的兩件事

2024-07-21 02:04:26
字體:
來源:轉載
供稿:網友
  • 事件捕捉(event capture)的實現問題
  • ie的高級事件處理模型的問題

一、事件捕捉(event capture)的實現問題

首先在說這件事前,先感謝一下realazy。 

w3c dom level2的事件模型規范中,事件在dom樹中的傳播過程(從根節點到目標節點)被分為了兩個階段:捕捉(capture)和冒泡(bubbling)。下面這個圖能大概的說明整個過程:

關于dom事件模型的兩件事_網頁設計VeVb.com整理轉載
(from w3c)

如果想創建一個捕捉事件,在支持w3c 事件模型的瀏覽器中,將addeventlistener的第三個參數設為true就好了。例如:

document.getelementbyid('foo').addeventlistener('click',function(){alert('hello, world!');},true);

前一陣因為想弄懂事件捕捉,所以做了點小實驗,分別在firefox 2、safari 3 on windows和opera 9上實踐了事件捕捉(當然,因為ie不支持事件捕捉,所以…),實驗的原理見下圖:

關于dom事件模型的兩件事_網頁設計VeVb.com整理轉載

id為div1和div2的兩個元素都被委派了捕捉階段的事件處理函數,這樣:

  • 當點擊#div1(藍色區域)時,應該會alert出”div1′
  • 當點擊#div2(黃色區域)時,應該會先alert出”div1′,再alert出”div2′,因為在事件捕捉階段,事件是從根元素向下傳播的,#div1是#div2的父元素,自然綁定在#div1上的click事件也會先于#div2上的click事件被執行。

然而,以上的設想只試用于firefox 2和safari 3 on windows,在opera 9中,事情會變成這樣:

  • 當點擊#div1(藍色區域)時,什么都不會發生
  • 當點擊#div2(黃色區域)時,會alert出”div1′,隨后什么都不會再發生

可以看出,在opera 9中,目標元素(targetelement)的click事件沒有被執行。通過realazy(orz…)的指點,找到了這篇文章:《event capture explained》,發現,

來opera中的實現才是正確的。此文中有一段話如是說
the dom spec states that capturing events should not fire on target, because the idea of a capturing event is to detect events before they reach their targets. because of bugs in gecko and safari, web content that is tested mostly with firefox or other gecko-based browsers sometimes expects capturing listeners to fire on target. such content will fail in opera 7, 8 and current releases of 9 because of its correct implementation of the standard.

大意是說:dom規范中陳述了捕捉型的事件不應該在目標元素上被執行,因為捕捉型事件的用意就是為了監測到達目標元素之前的事件。firefox和safari的實現都是帶有bug的。

再來看看w3c的dom events規范中的原話
a capturing eventlistener will not be triggered by events dispatched directly to the eventtarget upon which it is registered.

所以,在整個事件傳播中,被執行的順序是:

  1. 父元素中所有的捕捉型事件(如果有)自上而下地執行
  2. 目標元素的冒泡型事件(如果有)
  3. 父元素中所有的冒泡型事件(如果有)自下而上地執行

在了解了這些后,也許還是不要使用事件捕捉為妙,至少暫時不要。

|||

二、ie的高級事件處理模型的問題

重復綁定

ie下沒有addeventlistener,但是也有自己的attachevent,即所謂的microsoft model。二者的實現基本相同只是attachevent的第一個參數(事件類型)需要加”on”,而addeventlistener不用,另外attachevent因為不支持事件捕捉,所以也沒有第三個參數。

然而,attachevent還有一個很要命的問題:重復綁定事件。(這是從ppk on javascript中學到的)

一個例子:

function sayhello(){
alert('hello, world!');
}
// w3c model
$('div1').addeventlistener('click', sayhello, false);
$('div1').addeventlistener('click', sayhello, false);
// microsoft model
$('div1').attachevent('onclick', sayhello);
$('div1').attachevent('onclick', sayhello);

在w3c模型中,相同事件處理函數的綁定會被忽略,也就是說第二個$('div1').addeventlistener('click', sayhello, false);會被忽略。

而在microsoft模型中,第二個$('div1').attachevent('onclick', sayhello);同樣會被執行,所以,當你點擊#div1的時候,alert框會彈出來兩次。更有甚者,在detachevent時候,也同樣要detachevent兩次才能徹底把sayhello從#div1的click事件中刪除。

為什么不繼續使用alertid()了?

這是因為ie的事件模型的另一個缺陷,在alertid中,使用了this關鍵字來指代被委派了該事件處理函數的元素,這樣,在w3c模型中,alertid中的this指代了#div1或者#div2。

但是在microsoft模型中,缺少了對this的支持后,this.id就會變為undefined,因為這時候this指代了window對象。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 安丘市| 屯昌县| 华蓥市| 漳平市| 华安县| 开化县| 比如县| 盐边县| 乌拉特中旗| 襄樊市| 溧水县| 萝北县| 徐州市| 罗城| 东源县| 夏邑县| 衡阳市| 虹口区| 平利县| 安泽县| 双柏县| 哈尔滨市| 阜城县| 瓦房店市| 岗巴县| 炉霍县| 丰都县| 四会市| 山阳县| 梓潼县| 洮南市| 乌兰察布市| 扶绥县| 谷城县| 顺平县| 讷河市| 石台县| 定边县| 仙桃市| 龙泉市| 宣汉县|