什麼是冒泡
在頁面上可以有多個事件,也可以多個元素響應同一個事件。假設網頁上有兩個元素,其中一個元素嵌套在另一個元素裡,並且都被綁定了click事件,同時body元素上也綁定了click事件。
01
<div id="content">
02
外層div元素
03
<span>內層span元素</span>
04
外層div元素
05
</div>
06
07
<script type="text/javascript">
08
$(function(){
09
// 為span元素繫結click事件
10
$('span').bind("click",function(){
11
var txt = $('#msg').html() + "<p>內層span元素被點擊.<p/>";
12
$('#msg').html(txt);
13
});
14
// 為div元素繫結click事件
15
$('#content').bind("click",function(){
16
var txt = $('#msg').html() + "<p>外層div元素被點擊.<p/>";
17
$('#msg').html(txt);
18
});
19
// 為body元素繫結click事件
20
$("body").bind("click",function(){
21
var txt = $('#msg').html() + "<p>body元素被點擊.<p/>";
22
$('#msg').html(txt);
23
});
24
})
25
</script>
當單擊內部span元素,即觸發span元素的click事件時,會輸出3條記錄。只單擊內部span元素,就會觸發外部div元素和body元素 上綁定的click事件。這是由事件冒泡引起的。在單擊span元素的同時,也單擊了包含span元素的元素div和包含div元素的元素body,並且 每一個元素都會按照特定的順序響應click事件。
元素的click事件會按照以下順序“冒泡”。
<span>
<div>
<body>
之所以稱為冒泡,是因為事件會按照DOM的階層像水泡一樣不斷向上直至頂端。
事件冒泡引發的問題
事件冒泡可能會引起預料之外的效果。上例中,本來只想觸發<span>元素的click事件,然而<div>元素 和<body>元素的click事件也同時被觸發了。因此,有必要對事件的作用範圍進行限制。當單擊<span>元素時,只觸 發<span>元素的click事件,而不觸發<div>元素和<body>元素的click事件:當單 擊<div>元素時,只觸發<div>元素的click事件,而不觸發<body>元素的click事件。
事件對象
由於IE-DOM和標準DOM實現事件對象的方法各不相同,導致在不同瀏覽器中擷取事件對象變得比較困難。針對這個問題,JQuery進行了必要的擴充和封裝,從而使得在任何瀏覽器中都能很輕鬆地擷取事件對象以及事件對象的一些屬性。
在程式中使用事件對象非常簡單,只需要為函數添加一個參數,jQuery代碼如下:
1
$("element").bind("click",function(event){
2
//event : 事件對象
3
//...
4
});
這樣,當單擊“element”元素時,事件對象就被建立了。這個事件對象只有事件處理函數才能訪問到。事件處理函數執行完畢後,事件對象就被銷毀。
停止事件冒泡
停止事件冒泡可以阻止事件中其他對象的事件處理函數被執行。在JQuery中提供了stopPropagation()方法來停止事件冒泡。
1
$(function(){
2
// 為span元素繫結click事件
3
$('span').bind("click",function(event){
4
var txt = $('#msg').html() + "內層span元素被點擊";
5
$('#msg').html(txt);
6
event.stopPropagation(); // 阻止事件冒泡
7
});
8
})
當單擊<span>元素時,只會觸發<span>元素上的click事件,而不會觸發<div>元素和<body>元素的click事件。可以用同樣的方法解決<div>元素上的冒泡問題。
1
$('#content').bind("click",function(event){
2
var txt = $('#msg').html() + "<p>外層div元素被點擊.<p/>";
3
$('#msg').html(txt);
4
event.stopPropagation(); // 阻止事件冒泡
5
});
這樣,當單擊<span>元素或者<div>元素時,就只會輸出相應的內容,而不會輸出其他的內容。
阻止預設行為
網頁中的元素有自己預設的行為,例如,單擊超連結後會跳轉、單擊“提交”按鈕後表單會提交,有時需要阻止元素的預設行為。
在JQuery中,提供了preventDefault()方法來阻止元素的預設行為。
舉一個例子,在項目中,經常需要驗證表單,在單擊“提交”按鈕時,驗證表單內容,例如某元素是否是必要欄位,某元素長度是否夠6位等,當表單不符合提交條件時,要阻止表單的提交(預設行為)。
01
<form action="test.html">
02
使用者名稱:<input type="text" id="username" />
03
<br/>
04
<input type="submit" value="提交" id="sub"/>
05
</form>
06
07
$(function(){
08
$("#sub").bind("click",function(event){
09
var username = $("#username").val(); //擷取元素的值
10
if(username==""){ //判斷值是否為空白
11
$("#msg").html("<p>文字框的值不可為空.</p>"); //提示資訊
12
event.preventDefault(); //阻止預設行為 ( 表單提交 )
13
}
14
})
15
})
當使用者名稱為空白時,單擊“提交”按鈕,會出現提示,並且表單不能提交。只有在使用者名稱裡輸入內容後,才能提交表單。可見,preventDefault()方法能阻止表單的提交行為。
如果想同時對事件對象停止冒泡和預設行為,可以在事件處理函數中返同false。這是對在事件對象上同時調用stopPrapagation()方法和preventDefault()方法的一種簡寫方式。
在表單的例子中,可以把 event.preventDefault(); 改寫為: return false;
也可以把事件冒泡例子中的 event.stopPropaqation(); 改寫為: return false;
事件捕獲
事件捕獲和事件冒泡是剛好相反的兩個過程,事件捕獲是從最頂端往下開始觸發。還是冒泡事件的例子,其中元素的click事件會按照以下順序捕獲。
<body>
<div>
<span>
很顯然,事件捕獲是從最外層元素開始,然後再到最裡層元素。因此綁定的click事件,首先會傳遞給<body>元素,然後傳遞給<div>元素,最後才傳遞給<span>元素。
遺憾的是,並非所有主流瀏覽器都支援事件捕獲,並且這個缺陷無法通過JavaScript來修複。JQuery不交持事件捕獲,如果讀者需要使用事件捕獲,請直接使用原生的JavaScript。