基本問題很簡單。假設(shè)你的一個元素包含在另外一個元素中。
-----------------------------------<BR>| element1 |<BR>| ------------------------- |<BR>| |element2 | |<BR>| ------------------------- |<BR>| |<BR>-----------------------------------<BR>
這兩個元素都有onclick事件處理程序。如果用戶在element2上面單擊那么在元素2和元素1上都觸發(fā)了單擊事件。但是哪個事件先發(fā)生呢?哪個事件處理程序會先執(zhí)行呢?換句話說,事件順序(event order)是什么呢?
兩種模式
毫無疑問的,Netscape和微軟在過去那段很糟糕的日子里都做出了自己的決定。
Netscape說element1先發(fā)生的。這叫事件捕獲(event capturing)。
微軟覺得element2先發(fā)生的。這叫事件冒泡(event bubbling)。
這兩種事件順序剛好相反。IE只支持事件冒泡。Mozilla,Opera 7和Konqueror兩種都支持。早一些的Opear和iCab瀏覽器兩個都不支持。
事件捕獲
當你使用事件捕獲的時候
| |<BR>---------------| |-----------------<BR>| element1 | | |<BR>| --------- --| |----------- |<BR>| |element2 / | |<BR>| ------------------------- |<BR>| Event CAPTURING |<BR>-----------------------------------<BR>
element1的事件處理程序會先執(zhí)行,element2后執(zhí)行。
事件冒泡
但你使用事件冒泡的時候
/ <BR>---------------| |-----------------<BR>| element1 | | |<BR>| ---------- -| |----------- |<BR>| |element2 | | | |<BR>| ------------------------- |<BR>| Event BUBBLING |<BR>-----------------------------------<BR>
element2的事件處理程序會先執(zhí)行,element1的事件處理程序后執(zhí)行。
W3C模式
W3C決定在這場戰(zhàn)爭中保持重力。在W3C事件模型中任何事件發(fā)生都是首先被捕獲直到到達目標元素,然后再冒泡。
| | / <BR>-----------------| |--| |-----------------<BR>| element1 | | | | |<BR>| ----------- --| |--| |----------- |<BR>| |element2 / | | | |<BR>| -------------------------------- |<BR>| W3C event model |<BR>------------------------------------------<BR>
作為設(shè)計師的你,可以隨意選擇把事件處理程序注冊在捕獲還是冒泡階段。通過之前高級模式里面介紹的addEventListener()方法就可以完成。如果最后一個參數(shù)是true那么就設(shè)置成為事件捕獲,如果是false就設(shè)置為事件冒泡。
假設(shè)你這樣寫
element1.addEventListener('click',doSomething2,true)<BR>element2.addEventListener('click',doSomething,false)<BR>
如果用戶在element2上單擊就會發(fā)生下面的事情:
1、click事件發(fā)生在捕獲階段。這樣看來,如果element2的任何一個父元素有onclick事件處理程序那么都會執(zhí)行。
2、事件在element1上發(fā)現(xiàn)了doSomething2(),那么就會執(zhí)行它。
3、事件向下傳遞直到目標本身,再沒有其他的捕獲階段程序了。事件轉(zhuǎn)而進入冒泡階段然后就會執(zhí)行doSomething(),也就是element2注冊在冒泡階段的事件處理程序。
4、事件再向上傳遞再檢查是否有父元素在冒泡階段設(shè)置事件處理程序。這里沒有,所以什么也不會發(fā)生。
反過來:
element1.addEventListener('click',doSomething2,false)<BR>element2.addEventListener('click',doSomething,false)<BR>
現(xiàn)在如果用戶在element2上面點擊就會發(fā)生:
1、事件click發(fā)生在捕獲階段。事件會查找element2的父元素是否有在捕獲階段注冊事件處理程序,在這里沒有。
2、事件向下傳遞直到目標本身。然后開始冒泡階段,執(zhí)行dosomething(),這個是注冊在element2冒泡階段的事件處理程序。
3、事件繼續(xù)向上傳遞然后檢查是否有父元素在冒泡階段注冊了事件處理程序。
4、事件發(fā)現(xiàn)了element1.然后doSomething2()就被執(zhí)行了。