1. 事件目標
現在,事件處理程序中的變量event保存著事件對象。而event.target屬性保存著發生事件的目標元素。這個屬性是DOM API中規定的,但是沒有被所有浏覽器實現 。jQuery對這個事件對象進行了必要的擴展,從而在任何浏覽器中都能夠使用這個屬性。通過.target,可以確定DOM中首先接收到事件的元素(即實際被單擊的元素)。而且,我們知道this引用的是處理事件的DOM元素,所以可以編寫下列代碼:
復制代碼 代碼如下:
$(document).ready(function(){
$('#switcher').click(function(event){
$('#switcher .button').toggleClass('hidden');
})
})
$(document).ready(function(){
$('#switcher').click(function(event){
if(event.target==this){
$('#switcher .button').toggleClass('hidden');
}
})
})
此時的代碼確保了被單擊的元素是<div id="switcher"> ,而不是其他後代元素。現在,單擊按鈕不會再折疊樣式轉換器,而單擊邊框則會觸發折疊操作。但是,單擊標簽同樣什麼也不會發生,因為它也是一個後代元素。實際上,我們可以不把檢查代碼放在這裡,而是通過修改按鈕的行為來達到目標 。
2. 停止事件傳播
事件對象還提供了一個.stopPropagation()方法,該方法可以完全阻止事件冒泡。與.target類似,這個方法也是一種純JavaScript特性,但在跨浏覽器的環境中則無法安全地使用 。不過,只要我們通過jQuery來注冊所有的事件處理程序,就可以放心地使用這個方法。
下面,我們會刪除剛才添加的檢查語句event.target == this,並在按鈕的單擊處理程序中添加一些代碼:
復制代碼 代碼如下:
$(document).ready(function(){
$('#switcher .button').click(funtion(event){
//……
event.stopPropagation();
})
})
同以前一樣,需要為用作單擊處理程序的函數添加一個參數,以便訪問事件對象。然後,通過簡單地調用event.stopPropagation()就可以避免其他所有DOM元素響應這個事件。這樣一來,單擊按鈕的事件會被按鈕處理,而且只會被按鈕處理。單擊樣式轉換器的其他地方則可以折疊和擴展整個區域。
3. 默認操作
如果我們把單擊事件處理程序注冊到一個錨元素,而不是一個外層的<div>上,那麼就要面對另外一個問題:當用戶單擊鏈接時,浏覽器會加載一個新頁面。這種行為與我們討論的事件處理程序不是同一個概念,它是單擊錨元素的默認操作。類似地,當用戶在編輯完表單後按下回車鍵時,會觸發表單的submit事件,在此事件發生後,表單提交才會真正發生。
如果我們不希望執行這種默認操作,那麼在事件對象上調用.stopPropagation()方法也無濟於事,因為默認操作不是在正常的事件傳播流中發生的。在這種情況下,.preventDefault()方法則可以在觸發默認操作之前終止事件 。
提示 當在事件的環境中完成了某些驗證之後,通常會用到.preventDefault()。例如,在表單提交期間,我們會對用戶是否填寫了必填字段進行檢查,如果用戶沒有填寫相應字段,那麼就需要阻止默認操作。我們將在第8章詳細討論表單驗證。
事件傳播和默認操作是相互獨立的兩套機制,在二者任何一方發生時,都可以終止另一方。如果想要同時停止事件傳播和默認操作,可以在事件處理程序中返回false,這是對在事件對象上同時調用.stopPropagation()和.preventDefault()的一種簡寫方式。
補充:
復制代碼 代碼如下:
//單擊按鈕事件(改變文字樣式)
$(document).ready(function() {
$('#switcher .button').click(function() {
$('body').removeClass();
if (this.id == 'switcher-narrow') {
$('body').addClass('narrow');
}
else if (this.id == 'switcher-large') {
$('body').addClass('large');
}
$('#switcher .button').removeClass('selected');
$(this).addClass('selected');
});
});
//單擊按鈕外層div出發事件(隱藏按鈕)
$(document).ready(function() {
$('#switcher').click(function() {
$('#switcher .button').toggleClass('hidden');
});
});
現在的問題是,當點擊了按鈕時,同時觸發了隱藏按鈕事件。這是事件冒泡導致。
為了阻止事件冒泡,需要為隱藏按鈕函數添加一個參數:
復制代碼 代碼如下:
$(document).ready(function() {
$('#switcher').click(function(even) {
if(even.target==this){
$('#switcher .button').toggleClass('hidden');
}
});
});
even保存事件對象,even.target屬性保存發生事件的目標元素。可以確定DOM中首先接收到事件的元素。此時代碼確保了被單擊的是<div id="switcher">,而不是其後代元素。
也可以這樣處理,通過修改按鈕的行為來達到目的。
復制代碼 代碼如下:
$(document).ready(function() {
$('#switcher .button').click(function(even) {
$('body').removeClass();
if (this.id == 'switcher-narrow') {
$('body').addClass('narrow');
}
else if (this.id == 'switcher-large') {
$('body').addClass('large');
}
$('#switcher .button').removeClass('selected');
$(this).addClass('selected');
even.stopPropagation();
});
});
用JS阻止事件冒泡
事件冒泡: 當一個元素上的事件被觸發的時候,比如說鼠標點擊了一個按鈕,同樣的事件將會在那個元素的所有祖先元素中被觸發。這一過程被稱為事件冒泡;這個事件從原始元素開始一直冒泡到DOM樹的最上層。
可以用JS來阻止js事件冒泡。因為浏覽器的差異IE和FF的JS寫法有點不一樣。
IE用cancelBubble=true來阻止而FF下需要用stopPropagation方法。
下一下完整的代碼:
復制代碼 代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>無標題文檔</title>
<script type="text/javascript">
function aaaclick(){
alert("td click");
}
function bbbclick(evt){
alert("td click");
if (window.event) {
event.cancelBubble = true;
}else if (evt){
evt.stopPropagation();
}
}
function trclick(){
alert("tr click");
}
function tableclick(){
alert("table click");
}
</script>
<style type="text/css">
<!--
.tab {
border: 1px solid #0066FF;
cellpadding:0px;
cellspacing:0px;
}
.tab td{
border: 1px solid #0066FF;
}
-->
</style>
</head>
<body>
<p>點擊aaaa會觸發上層的onclick事件,點擊bbbb不會觸發上層onclick事件</p>
<table width="204" onclick="tableclick()" class="tab">
<tr >
<td width="96"> </td>
<td width="96"> </td>
</tr>
<tr onclick="trclick()">
<td onclick="aaaclick()">aaaa</td>
<td onclick="bbbclick(event)">bbbbb</td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</table>
</body>
</html>