亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

javascript事件冒泡詳解和捕獲、阻止方法

2019-11-20 20:50:16
字體:
來源:轉載
供稿:網友

一、事件的發生順序

這個問題的起源非常簡單,假設你在一個元素中又嵌套了另一個元素

復制代碼 代碼如下:

-----------------------------------
| element1                        |
|   -------------------------     |
|   |element2               |     |
|   -------------------------     |
|                                 |
-----------------------------------

:并且兩者都有一個onClick事件處理函數(event handler)。如果用戶單擊元素2,則元素1和元素2的單擊事件都會被觸發。但是哪一個事件先被觸發?哪一個事件處理函數會被首先執行?換句話說,事件的發生順序到底如何?

二、兩種模型

不出所料,在那些“不堪回首”(瀏覽器大戰)的日子里,Netscape和微軟有兩種截然不同的處理方法:

Netscape主張元素1的事件首先發生,這種事件發生順序被稱為捕獲型
微軟則保持元素2具有優先權,這種事件順序被稱為冒泡型
這兩種事件順序是截然相反的。Explorer瀏覽器只支持冒泡事件,Mozilla,Opera7和Konqueror兩者都支持。而更古老的opera和iCab兩者都不支持

三、捕獲型事件

當你使用捕獲型事件時

復制代碼 代碼如下:

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  / /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

:元素1的事件處理函數首先被觸發,元素2的事件處理函數最后被觸發

四、冒泡型事件

當你使用冒泡型事件時

復制代碼 代碼如下:

               / /
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

:元素2 的處理函數首先被觸發,元素1其次

五、W3C 模型

W3c明智的在這場爭斗中選擇了一個擇中的方案。任何發生在w3c事件模型中的事件,首是進入捕獲階段,直到達到目標元素,再進入冒泡階段

復制代碼 代碼如下:

                 | |  / /
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    / /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

為一個web開發者,你可以選擇是在捕獲階段還是冒泡階段綁定事件處理函數,這是通過addEventListener()方法實現的,如果這個函數的最后一個參數是true,則在捕獲階段綁定函數,反之false,在冒泡階段綁定函數。

假設你要做

復制代碼 代碼如下:

element1.addEventListener('click',doSomething2,true)

element2.addEventListener('click',doSomething,false)

如果用戶單擊元素2,則接下來會發生:

(事件在這里就像一個觀光客,由外至內游覽,逐漸接近被觸發的主要元素,然后又反向離開)

1.單擊事件首先進入捕獲階段開始(逐漸接近元素2的方向)。查看元素2的祖先元素中是否有在捕獲階段有onclick處理函數的
2.發現元素1有一個,于是doSomething2被執行
3.事件檢查到目標自己(元素2),捕獲階段沒有發現更多的處理函數了。事件開始進入冒泡階段,想當然執行doSomething(),這個綁定于元素2冒泡階段的函數。
4.事件向遠離元素2的方向,查看是否有任何祖先元素在冒泡階段綁定了一個處理函數。沒有這樣的情況,所以什么也沒有發生
相反的情況是:

復制代碼 代碼如下:

element1.addEventListener('click',doSomething2,false)

element2.addEventListener('click',doSomething,false)


現在如果用戶點擊元素2會發生:

1.單擊事件進入捕獲階段。查看元素2的祖先元素中是否有在捕獲階段有onclick處理函數的,結果一無所獲
2.事件檢查到目標自己。事件開始進入冒泡階段,并且執行綁定于元素2冒泡階段的函數。doSomething()
3.事件開始遠離目標,檢查元素2的祖先元素中是否有在冒泡階段綁定了處理函數的
4.發現了一個,于是元素1的doSomething2()被執行

六、兼容性和傳統模式

在支持w3c dom(文檔對象模型) 的瀏覽器中,傳統的事件綁定方法是

復制代碼 代碼如下:
element1.onclick = doSomething2;

默認被視為在綁定于冒泡階段

七、使用冒泡型事件

很少的開發人員會有意識的去使用冒泡型事件或者捕獲型事件。在他們今天制作的網頁中,沒有必要讓一個事件因為冒泡而被好幾個函數處理。但是有時用戶通常會很疑惑,因為在他們只點擊了一次鼠標之后出現了許多種情況(多個函數被執行,因為冒泡)。而大多數情況下你還是希望你的處理函數相互獨立的。當用戶點擊了某一個元素,發生什么,點擊另一個元素,又對應發生些什么,相互獨立,而不因為冒泡連鎖。

八、一直在發生

首先你要明白的是事件捕獲或者冒泡一直在發生。如果你給整個頁面文檔的定義一個通用onclick處理函數

復制代碼 代碼如下:

document.onclick = doSomething;
if (document.captureEvents) document.captureEvents(Event.CLICK);

在頁面上單擊任何元素的單擊事件,最終會冒泡至頁面最高文檔層,因此觸發那個通用的處理函數,除非之前一個處理函數明確的指出終止冒泡,這樣才冒泡才不會傳播到整個文檔層面


對上面代碼第二句的補充:

>>>先說IE
object.setCapture() 當一個object的被 setCapture 后,他的方法將會被繼承到整個文檔進行捕獲。
當不需要把方法繼承到整個文檔捕獲時,要用 object.releaseCapture()
>>>others
Mozilla 也有類似的功能,方法稍微不同
window.captureEvents(Event.eventType)
window.releaseEvents(Event.eventType)
>>>example

復制代碼 代碼如下:
//如果只有下面這句話,那只有點擊obj是才會觸發click    obj.onclick = function(){alert("something")}
//若加上下面這句話,則方法會被繼承到document(或者window,不同瀏覽器不同)來捕獲
obj.captureEvents(Event.click); //FF
obj.setCapture()  //IE

九、用法

因為任何事件傳播終止于頁面文檔(這個最高層),這使默認的事件處理函數變得可能,假設你有這樣一個頁面

復制代碼 代碼如下:

------------------------------------
| document                         |
|   ---------------  ------------  |
|   | element1    |  | element2 |  |
|   ---------------  ------------  |
|                                  |
------------------------------------
element1.onclick = doSomething;
element2.onclick = doSomething;
document.onclick = defaultFunction;

 

現在如果用戶單擊元素1或者元素2,doSomething()將被執行。如果你愿意的話,如果你不想讓事件冒泡至執行defaultFunction(),你可以在這里阻止事件冒泡向上傳播,。但是如果用戶點擊頁面上的其他部位,defaultFunction()還是會被執行。這樣的效果或許有時能用的上。

設置頁面­――使處理函數有范圍較大的觸發面積,在“拖拽效果”腳本中是必須的。一般來說在某一個元素層上發生 mousedown事件意味著選擇了這個元素,并且使它能夠響應mousemove事件。雖然mousedown通常綁定于這個元素層上以避免瀏覽器bug,但是其他兩者的事件函數的范圍必須是整個頁面(?)

記住瀏覽器學的第一法則(First Law of Browserology)是:一切皆有可能(anything can happen),并且是在你起碼有點準備的時候。所以有可能發生的是,用戶拖拽時,大幅度在頁面上移動他的鼠標,腳本卻不能在大幅度中做出反應,以至于鼠標也就不再停留在元素層上了

1.如果onmouseover處理函數綁定在元素層上,這個元素層不會再對鼠標的移動有任何反應,這會讓用戶覺得奇怪
2.如果onmouseup處理函數綁定在元素層上,事件也不能被觸發,后果是,用戶想放下這個元素層后,元素層持續對鼠標移動做出反應。這會引起(用戶)更多的迷惑(?)

所以在這個例子中,事件冒泡非常的有用,因為將你的處理函數放在頁面層能保證他們一直能被執行

十、把它給關了(阻止事件冒泡)

但是一般情況下,你會想關了所有的冒泡和捕獲以保證函數之間不會打擾到對方。除此之外,如果你的文檔結構相當的復雜(許多table之間相互嵌套或者諸如此類),你也會為了節省系統資源,而關閉冒泡。此時瀏覽器不得不檢查目標元素的每一個祖先,看是否它有一個處理函數。即使一個都沒有找到,剛剛的搜索同樣花費不少時間

在微軟的模型中,你必須設置事件的cancelBubble的屬性為true

復制代碼 代碼如下:
window.event.cancelBubble = true

在w3c模型中你必須調用事件的stopPropagation()方法
復制代碼 代碼如下:
e.stopPropagation()

這會阻止所有冒泡向外傳播。而作為跨瀏覽器解決方案應該這么作:
復制代碼 代碼如下:

function doSomething(e)

{
      if (!e) var e = window.event;

         e.cancelBubble = true;

         if (e.stopPropagation) e.stopPropagation();

}

在支持cancelBubble屬性的瀏覽器中設置cancelBubble無傷大雅。瀏覽器會聳一聳肩然后創造一個這個屬性。當然這也并不能真正的取消冒泡,但至少能保證這條命令是安全正確的

十一、currentTarget

像我們之前看到的一樣,一個事件用target或者是srcElement屬性用來表示事件究竟發生在哪個目標元素上(即用戶最初點擊的元素)。在我們的例子中是元素2,因為我們單擊了它。

非常重要的是,要明白在捕獲或者冒泡階段的目標元素是不變的,它始終與元素2相關聯。

但是假設我們綁定了以下函數

復制代碼 代碼如下:
element1.onclick = doSomething;

element2.onclick = doSomething;


如果用戶單擊元素2, doSomething()會被執行兩次。但是你怎么知道哪個html元素正在響應這個事件?target/srcElement也沒有給出線索,但人們總是更傾向于元素2,因為它是引起事件的原因(因為用戶點擊的是它)。
為了解決這個問題,w3c 增加了currentTarget這個屬性,它就指向正在處理事件的元素:這恰是我們需要的。很不幸的是微軟模型中并沒有相似的屬性
你也可以使用”this”關鍵字。在上面的例子中,它相當于正在處理事件的html元素,就像currentTarget。

十二、微軟模型的問題

但是當你使用微軟事件綁定模型時,this關鍵字并不相當于HTML元素。聯想缺少類似currentTarget屬性的微軟模型(?)――按上面的代碼操作的話,你這么做便意味著:

復制代碼 代碼如下:
element1.attachEvent('onclick',doSomething)

element2.attachEvent('onclick',doSomething)


你無法確切知道哪一個HTML元素正在負責處理事件,這是微軟事件綁定模型最嚴重的問題,對我來說,這也是我從不使用它的原因,哪怕是在開發僅供Windows下的IE的應用程序

我希望能夠盡快增加currentTarget類似的屬性――或者遵循標準?web開發者們需要這些信息

后記:

因為沒有實戰過javascript,所以這篇文章有些地方我并不是很理解,只能硬生的翻譯出來,比如談拖拽效果的那一段,如果大家有什么補充和疑問可以留言給我,謝謝支持啦!

 PS:這里再為大家推薦一款關于JS事件的在線查詢工具,歸納總結了JS常用的事件類型與函數功能:

javascript事件與功能說明大全:

http://tools.VeVB.COm/table/javascript_event

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频免费观看www| 97视频在线观看网址| 国产日产亚洲精品| 51午夜精品视频| 2021久久精品国产99国产精品| 久久久久久国产精品三级玉女聊斋| 成人免费网视频| 国产亚洲欧洲高清一区| 久久在线视频在线| 青青草成人在线| 91国内产香蕉| 欧美日韩在线一区| 中文字幕日韩在线观看| 一区二区欧美亚洲| 国产亚洲精品激情久久| 精品久久久久久久久久ntr影视| 高清欧美性猛交xxxx| 97国产一区二区精品久久呦| 久久久久久久久电影| 亚洲精品久久久久中文字幕二区| 欧美韩国理论所午夜片917电影| 国产精品视频最多的网站| 88xx成人精品| 亚洲欧美日韩在线一区| 日本久久久久久久久久久| 97超碰国产精品女人人人爽| 91精品国产综合久久香蕉922| 欧美一级视频一区二区| 97久久久免费福利网址| 日本一区二区三区在线播放| 久久久免费在线观看| 亚洲精品自拍第一页| 91午夜在线播放| 国产精品露脸自拍| 国产精品国产自产拍高清av水多| 精品自在线视频| 国产精品久久久久久久久免费| 国产999在线观看| 亚洲综合中文字幕68页| 亚洲男人天堂古典| 国产亚洲欧美日韩美女| 亚洲肉体裸体xxxx137| 久久久久九九九九| 91精品国产91| 久久久久久久久久久亚洲| 欧美激情视频一区二区三区不卡| 午夜精品久久久久久久白皮肤| 亚洲激情在线观看视频免费| 九九热在线精品视频| 亚洲欧美激情精品一区二区| 亚洲国产成人一区| 精品国内产的精品视频在线观看| 日本国产精品视频| 国产精品96久久久久久| 不卡av日日日| 麻豆成人在线看| 北条麻妃一区二区在线观看| 伊人成人开心激情综合网| 久久国产精品偷| 日韩中文字幕在线观看| 欧美性xxxx极品hd满灌| 另类天堂视频在线观看| 国产精品一区专区欧美日韩| 欧美视频13p| 2019中文字幕免费视频| 欧美精品在线极品| 青青青国产精品一区二区| 久久99久国产精品黄毛片入口| 一区二区三区久久精品| 日韩中文字幕国产| 日韩av手机在线看| 久久中文字幕在线视频| 不卡av在线网站| 亚洲欧美国产高清va在线播| 91精品国产99久久久久久| 另类天堂视频在线观看| 亚洲人成网站777色婷婷| 精品magnet| 成人乱人伦精品视频在线观看| 精品女厕一区二区三区| 97av在线视频免费播放| 国产精品永久免费| 一区二区三区视频观看| 国产精品com| 91精品国产高清自在线| 欧美在线视频网| 国产成人精品久久久| 日产日韩在线亚洲欧美| 久久综合色影院| 7777精品视频| 精品国产一区久久久| 国产精品久久久久不卡| xxx欧美精品| 黑人巨大精品欧美一区免费视频| 国产成人精品电影久久久| 亚洲自拍偷拍色片视频| 日韩在线中文字| 欧美一级大片在线观看| 91成人在线播放| 国产精品女人网站| 九九热r在线视频精品| 久久精品在线视频| 亚洲福利精品在线| 日韩欧美亚洲综合| 国产精品九九久久久久久久| 91精品综合久久久久久五月天| www.亚洲人.com| 性欧美亚洲xxxx乳在线观看| 亚洲一二在线观看| 日韩美女在线观看一区| 亚洲欧美色图片| 国产精品久久久久影院日本| 中文字幕v亚洲ⅴv天堂| 成人美女免费网站视频| 5252色成人免费视频| 亚洲综合中文字幕在线| 亚洲美女自拍视频| 黄色精品在线看| 国产欧美日韩免费看aⅴ视频| 97婷婷大伊香蕉精品视频| 亚洲电影免费观看高清完整版在线观看| 国产在线拍揄自揄视频不卡99| 久久精品国产精品亚洲| 91麻豆国产语对白在线观看| 91精品国产自产在线观看永久| 超碰91人人草人人干| 成人免费视频网址| 亚洲人成网站777色婷婷| 色系列之999| 亚洲精品日韩激情在线电影| 亚洲综合一区二区不卡| 国产成人精品在线| 日韩精品视频中文在线观看| 国产在线高清精品| 欧美激情视频一区二区三区不卡| 国产欧美一区二区白浆黑人| 日韩av免费在线看| 国产丝袜一区二区三区| 久久久亚洲精品视频| 亚洲天堂成人在线视频| 日本欧美国产在线| 大桥未久av一区二区三区| 海角国产乱辈乱精品视频| 亚洲大尺度美女在线| 96国产粉嫩美女| 欧美日韩色婷婷| 91深夜福利视频| 精品久久在线播放| 国产一区二区在线免费视频| 日韩av在线不卡| 成人午夜激情网| 成人午夜激情免费视频| 国产亚洲精品久久久久久| 色综合伊人色综合网站| 国产精品一久久香蕉国产线看观看| 久久久国产精彩视频美女艺术照福利| 91在线免费网站| 色噜噜国产精品视频一区二区| 成人午夜黄色影院| 日本韩国欧美精品大片卡二| 国产精品国产自产拍高清av水多| 国产一区二区三区精品久久久| 欧美性猛交xxxx免费看漫画| 欧美在线视频在线播放完整版免费观看|