這個問題也是老生常談了,寫這篇文章的主要目的是進行下梳理,了解自己知識點的掌握程度,也希望對大家有所幫助。
在說如何阻止事件冒泡和默認事件之前先來說說什么是事件冒泡和默認事件(行為)?
事件冒泡:
在一個對象上觸發(fā)某類事件(比如點擊事件),如果此對象定義了此事件的處理程序,那么此事件就會調(diào)用這個處理程序,如果沒有定義此事件處理程序或者事件返回true,那么這個事件會向這個對象的父級對象傳播,從里到外,直至它被處理(父級對象所有同類事件都將被激活),或者它到達了對象層次的最頂層,即document對象(有些瀏覽器是window)。
IE5冒泡會到document終止,IE6的話在冒泡到document之前還會冒泡到html,Mozilla1.0及更高版本則會冒泡到window終止。
Netscape4.0使用了另一種稱為捕獲型事件(eventcapturing)的解決方案、事件的捕獲和冒泡剛好相反的兩種過程——捕獲型事件中,事件從最不精確的對象(document對象)開始觸發(fā),然后到最精確(也可以在窗口級別捕獲事件,不過必須由開發(fā)人員特別指定)。Netscape4.0不會將頁面上的很多元素暴露給事件。
DOM事件流:
DOM(文檔對象模型)結(jié)構(gòu)是一個樹型結(jié)構(gòu),當一個HTML元素產(chǎn)生一個事件時,該事件會在元素結(jié)點與根節(jié)點之間按特定的順序傳播,路徑所經(jīng)過的節(jié)點都會收到該事件,這個傳播過程可稱為DOM事件流。事件順序有兩種類型:事件捕捉和事件冒泡。
一個標準的DOM事件模型:
DOM標準同時支持兩種事件模型,即捕獲型事件與冒泡型事件,但是,捕獲型事件先發(fā)生。兩種事件流都會觸發(fā)DOM中的所有對象,從document對象開始,也在document對象結(jié)束(大部分兼容標準的瀏覽器會繼續(xù)將事件是捕捉/冒泡延續(xù)到window對象)。在與DOM兼容的瀏覽器中點擊
注意因為事件的目標(
要注意的問題:
1)focus、blur和scroll事件不會冒泡。文檔元素上的load事件會冒泡,但它會在document對象上停止冒泡而不會傳播到window對象。只有當整個文檔都加載完畢時才會觸發(fā)window對象的load事件。
2)阻止冒泡并不會阻止默認行為,比如submit按鈕被點擊后會提交表單數(shù)據(jù)。
什么情況下我們需要阻止冒泡事件呢?
比如現(xiàn)在有三個div盒子層層嵌套,我們需要點擊不同的div盒子時執(zhí)行各自的點擊事件。demo代碼如下:
HTML:
JS:
var lg = document.getElementById("lg");
var md = document.getElementById("md");
var sm = document.getElementById("sm");
lg.onclick = function()?{
alert("我是最外層的盒子lg");
};
md.onclick = function()?{
alert("我是中間的盒子md");
};
sm.onclick = function()?{
alert("我是最里面的盒子sm");
};
當我們點擊最里面的盒子sm的時候,瀏覽器會依次彈出"我是最里面的盒子sm","我是中間的盒子md","我是最外層的盒子lg"。并不是我們所期望的那樣點擊當前的盒子只執(zhí)行當前盒子的點擊事件。這正是因為事件冒泡的原因而導致的結(jié)果,這個時候我們就需要阻止事件冒泡。
如何阻止事件冒泡?
方法一:
使用stopPropagation()方法,使用event對象調(diào)用即可,但是該方法不支持IE9以下的瀏覽器,上述例子代碼修改后如下:
var lg = document.getElementById("lg");
var md = document.getElementById("md");
var sm = document.getElementById("sm");
lg.onclick = function()?{
alert("我是最外層的盒子lg");
};
md.onclick = function()?{
alert("我是中間的盒子md");
event.stopPropagation();
};
sm.onclick = function()?{
alert("我是最里面的盒子sm");
event.stopPropagation();
};
IE8以下的瀏覽器的IE事件對象有一個cancelBubble屬性,設(shè)置這個屬性為true,則可以阻止事件冒泡。
我們可以將阻止事件冒泡封裝成一個函數(shù),代碼如下:
//document.all 用于判斷是否IE瀏覽器
//IE:cancelBubble
//Firefox: stopPropagation
function stopEventBubbling(event)?{
var e = window.event || event;
if(document.all)?{
e.cancelBubble = true;
}
else {
e.stopPropagation();
}
}
方法二:
JQ提供兩種方法,第一種是stopPropagation(),使用時直接用event調(diào)用即可。
第二種是return false,代碼如下:
$("#sm").click(function()?{
alert("我是最里面的盒子sm");
return false;
});
這兩種方法是有區(qū)別的。return false不僅阻止了事件冒泡,還阻止了事件本身。stopPropagation()方法只會阻止事件冒泡,不會阻止事件本身。
默認事件:
瀏覽器的一些默認的行為。例如:點擊超鏈接跳轉(zhuǎn),點擊鼠標右鍵會彈出菜單,滑動滾輪控制滾動條……
如何阻止默認事件?
可以使用preventDefault()方法,直接使用event對象調(diào)用即可,但是該方法不支持IE9以下的瀏覽器,IE事件對象有一個屬性returnValue,默認是true,當將其設(shè)置為false時,則可以取消事件默認行為,同樣使用event對象調(diào)用。
我們可以將取消默認行為的方法封裝成一個函數(shù),代碼如下:
function cancelHandler(event)?{
var e = window.event || event;
if(document.all)?{
e.returnValue = false;
}
else {
e.preventDefault();
}
}
參考文獻:
《JavaScript權(quán)威指南》
如果你在本文中發(fā)現(xiàn)錯誤或者有異議的地方,可以在評論區(qū)留言,謝謝!