DOM事件標(biāo)準(zhǔn)定義了兩種事件流,這兩種事件流有著顯著的不同并且可能對(duì)你的應(yīng)用有著相當(dāng)大的影響。這兩種事件流分別是捕獲和冒泡。和許多Web技術(shù)一樣,在它們成為標(biāo)準(zhǔn)之前,Netscape和微軟各自不同地實(shí)現(xiàn)了它們。Netscape選擇實(shí)現(xiàn)了捕獲事件流,微軟則實(shí)現(xiàn)了冒泡事件流。幸運(yùn)的是,W3C決定組合使用這兩種方法,并且大多數(shù)新瀏覽器都遵循這兩種事件流方式。
默認(rèn)情況下,事件使用冒泡事件流,不使用捕獲事件流。然而,在Firefox和Safari里,你可以顯式的指定使用捕獲事件流,方法是在注冊(cè)事件時(shí)傳入useCapture參數(shù),將這個(gè)參數(shù)設(shè)為true。下面用個(gè)例子分別來(lái)測(cè)試這兩種事件流。
1、冒泡事件流
當(dāng)事件在某一DOM元素被觸發(fā)時(shí),例如用戶(hù)在客戶(hù)名字節(jié)點(diǎn)上點(diǎn)擊鼠標(biāo),事件將跟隨著該節(jié)點(diǎn)繼承自的各個(gè)父節(jié)點(diǎn)冒泡穿過(guò)整個(gè)的DOM節(jié)點(diǎn)層次,直到它遇到依附有該事件類(lèi)型處理器的節(jié)點(diǎn),此時(shí),該事件是onclick事件。在冒泡過(guò)程中的任何時(shí)候都可以終止事件的冒泡,在遵從W3C標(biāo)準(zhǔn)的瀏覽器里可以通過(guò)調(diào)用事件對(duì)象上的stopPropagation()方法,在Internet Explorer里可以通過(guò)設(shè)置事件對(duì)象的cancelBubble屬性為true。如果不停止事件的傳播,事件將一直通過(guò)DOM冒泡直至到達(dá)文檔根。
測(cè)試的HTML文件,其中用到了mootools-release-1.11.js,對(duì)mootools的代碼進(jìn)行了改動(dòng):
addListener: function(type, fn,setCapture){
if (this.addEventListener) this.addEventListener(type, fn, setCapture);
else {
this.attachEvent('on' + type, fn);
if (setCapture) this.setCapture(true);
}
return this;
}
給addListener方法里增加了setCapture參數(shù),用于測(cè)試捕獲事件流。
<body>
<div id="dd1-ct" style="width:400px;height:400px;border:1px solid #999;padding:2px">Container
<div id="dd1-item1" style="width:200px;height:200px;border:1px solid #999;padding:2px">Item1
<div id="dd1-item2" style="width:100px;height:100px;border:1px solid #999;padding:2px">Item2</div>
</div>
</div>
<div id='rh'></div>
</body>
效果:

js:
fn1=function(e){
// e.stopPropagation();
$('rh').innerHTML+='Item1 clicked!******';
};
fn2=function(e){
// e.stopPropagation();
$('rh').innerHTML+='Item2 clicked!-------';
};
fn=function(e){
// e.stopPropagation();
$('rh').innerHTML+='Container clicked!&&&&&&&&';
};
$('dd1-item2').addListener('click', fn2.bindWithEvent(),false);
$('dd1-item1').addListener('click', fn1.bindWithEvent(),false);
$('dd1-ct').addListener('click', fn.bindWithEvent(),false);
測(cè)試結(jié)果ie和ff下效果一致:?jiǎn)螕鬷tem2,會(huì)依次觸發(fā)fn2、fn1、fn;單擊item1,會(huì)依次觸發(fā)fn1、fn;單擊Container,只會(huì)觸發(fā)fn;當(dāng)在任何一個(gè)事件處理器里調(diào)用e.stopPropagation();都會(huì)阻止事件的冒泡。
2、捕獲事件流
事件的處理將從DOM層次的根開(kāi)始,而不是從觸發(fā)事件的目標(biāo)元素開(kāi)始,事件被從目標(biāo)元素的所有祖先元素依次往下傳遞。在這個(gè)過(guò)程中,事件會(huì)被從文檔根到事件目標(biāo)元素之間各個(gè)繼承派生的元素所捕獲,如果事件監(jiān)聽(tīng)器在被注冊(cè)時(shí)設(shè)置了useCapture屬性為true,那么它們可以被分派給這期間的任何元素以對(duì)事件做出處理;否則,事件會(huì)被接著傳遞給派生元素路徑上的下一元素,直至目標(biāo)元素。事件到達(dá)目標(biāo)元素后,它會(huì)接著通過(guò)DOM節(jié)點(diǎn)再進(jìn)行冒泡。
這里ie與ff存在著很大的差異,甚至ie6與ie7的表現(xiàn)也各不相同,所以分開(kāi)測(cè)試。
a、ff
事件從從DOM層次的根開(kāi)始往下傳遞時(shí),會(huì)被useCapture屬性為true的事件監(jiān)聽(tīng)器所捕獲,而到達(dá)目標(biāo)元素再?gòu)哪繕?biāo)元素冒泡時(shí),則會(huì)被useCapture屬性為false的事件監(jiān)聽(tīng)器所捕獲。當(dāng)在任何一個(gè)事件處理器里調(diào)用e.stopPropagation();都會(huì)阻止事件的傳播。
b、ie6
用事實(shí)說(shuō)話(huà):
第一種情況:
$('dd1-item2').addListener('click', fn2.bindWithEvent(),true);
$('dd1-item1').addListener('click', fn1.bindWithEvent(),true);
$('dd1-ct').addListener('click', fn.bindWithEvent(),true);
單擊瀏覽器的任何位置,都只是觸發(fā)fn;
第二種情況:
$('dd1-item2').addListener('click', fn2.bindWithEvent(),true);
$('dd1-item1').addListener('click', fn1.bindWithEvent(),true);
$('dd1-ct').addListener('click', fn.bindWithEvent(),false);
單擊瀏覽器的任何位置,會(huì)依次觸發(fā)fn1、fn;
第三種情況:
$('dd1-item2').addListener('click', fn2.bindWithEvent(),true);
$('dd1-item1').addListener('click', fn1.bindWithEvent(),false);
$('dd1-ct').addListener('click', fn.bindWithEvent(),false);
單擊瀏覽器的任何位置,會(huì)依次觸發(fā)fn2、fn1、fn;
結(jié)論:如果HTML元素捕獲了通過(guò)該元素的setCapture()方法對(duì)這個(gè)元素的設(shè)置,依附于該元素的處理器將會(huì)被事件觸發(fā),即使setCapture()方法
被調(diào)用的這個(gè)元素不在目標(biāo)元素的祖先路徑中。事實(shí)上你甚至單擊瀏覽器的非頁(yè)面部分都會(huì)觸發(fā)事件處理器。并且事件一旦被捕獲就不會(huì)繼續(xù)再
往下傳播(即使該元素在目標(biāo)元素的祖先路徑中),而是立刻冒泡。e.stopPropagation();會(huì)阻止事件的冒泡。
c、ie7
測(cè)試效果與冒泡事件流一致。將對(duì)捕獲事件流的支持干掉了?
結(jié)論:正如mootools所做的,避免捕獲事件流。
http://www.tkk7.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:)
posted on 2008-03-02 14:54
ronghao 閱讀(2004)
評(píng)論(0) 編輯 收藏 所屬分類(lèi):
ajax相關(guān)