JavaScript 事件冒泡應(yīng)用實例分析
更新時間:2010年01月11日 00:54:38 作者:
在一些傳統(tǒng)的小型WEB應(yīng)用開發(fā)過程中,JavaScript通常只是拿來做表單驗證而以,所以你很少會遇到因為JavaScript事件冒泡而影響功能的實現(xiàn)情況,又或者事件冒泡對最終實現(xiàn)效果影響不大,可忽略。
然而,在今天一些大型的WEB交互項目中,比如大型的WebGame項目,JavaScript事件冒泡影響是值得重視的。本文通過一個簡單的例子來講解JavaScript事件冒泡及使用注意事項。
如果你對JavaScript事件冒泡還沒有什么印象,不妨先看看我之前寫的一篇博客《JavaScript事件冒泡簡介及應(yīng)用》。本文講究實用,不在對JavaScript事件冒泡基礎(chǔ)知識進行過多的闡述。
在文章開始之前,現(xiàn)在先看看下面這樣一個需求:下面HTML假設(shè)描述的是一個WebGame項目包裹欄(玩過網(wǎng)游的人應(yīng)該知道什么是包裹欄或物品欄)的外框架,拖動這個包裹標(biāo)題欄可以拖動這個包裹到頁面上任何位置,而點擊標(biāo)題欄右側(cè)的“×”關(guān)閉按鈕可以關(guān)閉這個包裹欄的顯示。你通過觀察HTML結(jié)構(gòu),可以發(fā)現(xiàn)那個關(guān)閉按鈕其實是一個A鏈接,而且是作為標(biāo)題欄H5的子元素存在。要想拖動一個元素,我們會想到向拖動的句柄元素注冊mousedown事件,而點擊或“單擊”關(guān)閉按鈕就關(guān)閉這個包裹。根據(jù)這個需求,我們很快得到下面這樣的代碼。

[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
在上面的例子中,你發(fā)現(xiàn)點擊關(guān)閉按鈕的時候,標(biāo)題欄的mousedown事件也觸發(fā)了,顯然這是在你意料之中的,因為你知道這正是JavaScript事件冒泡在起作用。其實你真正要的效果是點關(guān)閉按鈕的時候,不要執(zhí)行標(biāo)題H5注冊的mousedown事件,于是你想到了阻止事件冒泡,接著代碼修改成下面這樣:
<div id="box">
<h5 onmousedown="startDrag();"><a onclick="closeBox(event);" href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox(e)
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
stopBubble(e);
}
//阻止事件冒泡函數(shù)
function stopBubble(e)
{
if (e && e.stopPropagation)
e.stopPropagation();
else
window.event.cancelBubble=true;
}
</script>
結(jié)果你發(fā)現(xiàn)單擊關(guān)閉按鈕的時候,標(biāo)題H5注冊的mousedown事件還是執(zhí)行了,這是怎么回事呢?其實細心的你可能發(fā)現(xiàn),H5標(biāo)題和A鏈接注冊的事件不是一樣的,在上面的代碼中,我們在A鏈接注冊的click事件中調(diào)用阻止事件方法,這只是意味著其父元素注冊的“同類事件”不會執(zhí)行,意思是說如果H5標(biāo)題也注冊了click事件,這個click事件不會執(zhí)行,而這里的mousedown就繼續(xù)執(zhí)行了。這里的mousedown執(zhí)行不是因為你點中標(biāo)題欄而發(fā)生的,是由于你在單擊click的時候伴隨產(chǎn)生mousedown事件,然后又由于JavaScript事件冒泡機制的存在,事件向父級廣播并被H5標(biāo)題mousedown注冊方法捕獲。關(guān)于對這點的理解,可以參考我另外一篇博客《當(dāng)onmousedown、onmouseup、onclick同時應(yīng)用于同一個標(biāo)簽節(jié)點Element》?,F(xiàn)在,通過分析,你應(yīng)該知道怎么做了,小改上面的代碼,只要把A鏈接的click事件改成與H5標(biāo)題一樣的mousedown事件,你想要的效果就實現(xiàn)了。
相關(guān)話題:
現(xiàn)在講講如何在使用jQuery開發(fā)時輕松阻止事件冒泡。jQuery作為一個優(yōu)秀的腳本框架,對事件的封裝及瀏覽器兼容處理自然也是很出眾的。想了解更多也可閱讀我的另外一篇博客《利用jQuery的$.event.fix函數(shù)統(tǒng)一瀏覽器event處理》。
使用jQuery要想阻止事件冒泡方法有二:
1、利用jQuery做過兼容處理的event對象,直接使用event.preventDefault(),舉例代碼如下:
<script type="text/javascript" src="http://img.jb51.net/jslib/jquery/jquery.js"></script>
<div id="box">
<h5 onmousedown="startDrag();"><a onmousedown="closeBox(event);" href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox(e)
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
var event = $.event.fix(e);
event.stopPropagation();
}
</script>
2、在jQuery綁定的函數(shù)中返回false,即return false。注意:不是使用jQuery綁定的方法返回false是沒有用的。代碼如下:
<script type="text/javascript" src="http://img.jb51.net/jslib/jquery/jquery.js"></script>
<div id="box">
<h5 onmousedown="startDrag();"><a href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox()
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
return false;
}
$('#box a').bind('mousedown',closeBox);
</script>
最后還要說明一下,利用第二個方法阻止事件冒泡,同時也阻止了瀏覽器的默認行為,在jQuery事件處理的源代碼的handle方法中(jQuery JavaScript Library v1.3.2非壓縮代碼2700行)我們可以看到向下面這樣的處理,event.preventDefault()用于阻止瀏覽器默認行為。
handle : function(event)
{
//other code......
if (ret === false)
{
event.preventDefault();
event.stopPropagation();
}
//other code......
}
作者:WebFlash
如果你對JavaScript事件冒泡還沒有什么印象,不妨先看看我之前寫的一篇博客《JavaScript事件冒泡簡介及應(yīng)用》。本文講究實用,不在對JavaScript事件冒泡基礎(chǔ)知識進行過多的闡述。
在文章開始之前,現(xiàn)在先看看下面這樣一個需求:下面HTML假設(shè)描述的是一個WebGame項目包裹欄(玩過網(wǎng)游的人應(yīng)該知道什么是包裹欄或物品欄)的外框架,拖動這個包裹標(biāo)題欄可以拖動這個包裹到頁面上任何位置,而點擊標(biāo)題欄右側(cè)的“×”關(guān)閉按鈕可以關(guān)閉這個包裹欄的顯示。你通過觀察HTML結(jié)構(gòu),可以發(fā)現(xiàn)那個關(guān)閉按鈕其實是一個A鏈接,而且是作為標(biāo)題欄H5的子元素存在。要想拖動一個元素,我們會想到向拖動的句柄元素注冊mousedown事件,而點擊或“單擊”關(guān)閉按鈕就關(guān)閉這個包裹。根據(jù)這個需求,我們很快得到下面這樣的代碼。

[Ctrl+A 全選 注:引入外部Js需再刷新一下頁面才能執(zhí)行]
在上面的例子中,你發(fā)現(xiàn)點擊關(guān)閉按鈕的時候,標(biāo)題欄的mousedown事件也觸發(fā)了,顯然這是在你意料之中的,因為你知道這正是JavaScript事件冒泡在起作用。其實你真正要的效果是點關(guān)閉按鈕的時候,不要執(zhí)行標(biāo)題H5注冊的mousedown事件,于是你想到了阻止事件冒泡,接著代碼修改成下面這樣:
復(fù)制代碼 代碼如下:
<div id="box">
<h5 onmousedown="startDrag();"><a onclick="closeBox(event);" href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox(e)
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
stopBubble(e);
}
//阻止事件冒泡函數(shù)
function stopBubble(e)
{
if (e && e.stopPropagation)
e.stopPropagation();
else
window.event.cancelBubble=true;
}
</script>
結(jié)果你發(fā)現(xiàn)單擊關(guān)閉按鈕的時候,標(biāo)題H5注冊的mousedown事件還是執(zhí)行了,這是怎么回事呢?其實細心的你可能發(fā)現(xiàn),H5標(biāo)題和A鏈接注冊的事件不是一樣的,在上面的代碼中,我們在A鏈接注冊的click事件中調(diào)用阻止事件方法,這只是意味著其父元素注冊的“同類事件”不會執(zhí)行,意思是說如果H5標(biāo)題也注冊了click事件,這個click事件不會執(zhí)行,而這里的mousedown就繼續(xù)執(zhí)行了。這里的mousedown執(zhí)行不是因為你點中標(biāo)題欄而發(fā)生的,是由于你在單擊click的時候伴隨產(chǎn)生mousedown事件,然后又由于JavaScript事件冒泡機制的存在,事件向父級廣播并被H5標(biāo)題mousedown注冊方法捕獲。關(guān)于對這點的理解,可以參考我另外一篇博客《當(dāng)onmousedown、onmouseup、onclick同時應(yīng)用于同一個標(biāo)簽節(jié)點Element》?,F(xiàn)在,通過分析,你應(yīng)該知道怎么做了,小改上面的代碼,只要把A鏈接的click事件改成與H5標(biāo)題一樣的mousedown事件,你想要的效果就實現(xiàn)了。
相關(guān)話題:
現(xiàn)在講講如何在使用jQuery開發(fā)時輕松阻止事件冒泡。jQuery作為一個優(yōu)秀的腳本框架,對事件的封裝及瀏覽器兼容處理自然也是很出眾的。想了解更多也可閱讀我的另外一篇博客《利用jQuery的$.event.fix函數(shù)統(tǒng)一瀏覽器event處理》。
使用jQuery要想阻止事件冒泡方法有二:
1、利用jQuery做過兼容處理的event對象,直接使用event.preventDefault(),舉例代碼如下:
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="http://img.jb51.net/jslib/jquery/jquery.js"></script>
<div id="box">
<h5 onmousedown="startDrag();"><a onmousedown="closeBox(event);" href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox(e)
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
var event = $.event.fix(e);
event.stopPropagation();
}
</script>
2、在jQuery綁定的函數(shù)中返回false,即return false。注意:不是使用jQuery綁定的方法返回false是沒有用的。代碼如下:
復(fù)制代碼 代碼如下:
<script type="text/javascript" src="http://img.jb51.net/jslib/jquery/jquery.js"></script>
<div id="box">
<h5 onmousedown="startDrag();"><a href="javascript:void(0);">×</a></h5>
<div id="testInfo"></div>
</div>
<script type="text/javascript">
function startDrag()
{
document.getElementById('testInfo').innerHTML += 'startDrag<br/>';
}
function closeBox()
{
document.getElementById('testInfo').innerHTML += 'closeBox<br/>';
return false;
}
$('#box a').bind('mousedown',closeBox);
</script>
最后還要說明一下,利用第二個方法阻止事件冒泡,同時也阻止了瀏覽器的默認行為,在jQuery事件處理的源代碼的handle方法中(jQuery JavaScript Library v1.3.2非壓縮代碼2700行)我們可以看到向下面這樣的處理,event.preventDefault()用于阻止瀏覽器默認行為。
復(fù)制代碼 代碼如下:
handle : function(event)
{
//other code......
if (ret === false)
{
event.preventDefault();
event.stopPropagation();
}
//other code......
}
作者:WebFlash
您可能感興趣的文章:
相關(guān)文章
JavaScript獲取網(wǎng)頁中第一個圖片id的方法
這篇文章主要介紹了JavaScript獲取網(wǎng)頁中第一個圖片id的方法,涉及javascript中document.images方法的使用技巧,需要的朋友可以參考下2015-04-04
不用AJAX和IFRAME,說說真正意義上的ASP+JS無刷新技術(shù)
注明:以下方法都經(jīng)過實例和開發(fā)的長期驗證,其實這些技術(shù)早就有,今天只不過自己歸納一下2008-09-09
如何在微信小程序?qū)崿F(xiàn)一個幸運轉(zhuǎn)盤小游戲
這篇文章主要給大家介紹了關(guān)于如何在微信小程序?qū)崿F(xiàn)一個幸運轉(zhuǎn)盤小游戲的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
javascript實現(xiàn)無限級select聯(lián)動菜單
這篇文章主要介紹了javascript實現(xiàn)無限聯(lián)動菜單的方法和示例,思路非常棒,需要的朋友可以參考下2015-01-01
js change,propertychange,input事件小議
github上關(guān)于mootools一個issue的討論很有意思,所以就想測試記錄下。感興趣的可以點擊原頁面看看2011-12-12
JavaScript中Function與Object的關(guān)系
本文主要介紹了JavaScript中Function與Object的關(guān)系,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05
淺談javascript中的prototype和__proto__的理解
這篇文章主要介紹了淺談javascript中的prototype和__proto__的理解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
詳解JavaScript的數(shù)據(jù)類型以及數(shù)據(jù)類型的轉(zhuǎn)換
這篇文章主要介紹了JavaScript的數(shù)據(jù)類型以及數(shù)據(jù)類型的轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04

