一、什麼是事件冒泡?
當一個事件發生的時候,該事件總是有一個事件源,即引發這個事件的對象,一個事件不能憑空産生,這就是事件的發生。
當事件發生後,這個事件就要開始傳播。為什麼要傳播呢?因為事件源本身并沒有處理事件的能力。例如我們點選一個按鈕時,就會産生一個click事件,但這個按鈕本身不能處理這個事件(廢話),事件必須從這個按鈕傳播出去,進而到達能夠處理這個事件的代碼中(例如我們給按鈕的onclick屬性賦一個函數的名字,就是讓這個函數去處理該按鈕的click事件)。
當事件在傳播過程中,找到了一個能夠處理它的函數,這時候我們就說這個函數捕捉到了這個事件。 說到這裡,關鍵的問題來了,那就是一個函數是如何捕捉一個事件的呢?這就涉及到事件的冒泡了。
為了更好地了解冒泡的概念,我建議你現在想象一下你的面前放着一杯水,但這杯水和我們平時看到的有點點不同,它分為數層,每一層又分成一或多個區域,最頂層是我們熟悉的視窗對象(即window對象),下一層分為好幾個區域(document對象、history對象等等),而document對象的下一層又分為多個子對象。 這些對象的層次關系構成了DOM中的對象樹。
事件的傳播是有方向的,當點選一個按鈕時所産生的事件從這個按鈕處開始向上傳播(就像一個水泡從杯底冒上來,這就是之是以叫事件冒泡的原因),但這個事件總是尋找特定的屬性是否有值。例如按鈕的click事件先尋找在按鈕上是否有onclick屬性的有意義的定義(即該屬性指向一個存在的函數或一段可執行的語句),如果有,執行這個函數或語句;然後事件繼續向上傳播,到達按鈕的上一層對象(例如一個form對象或document對象,總之是包含了按鈕的父對象),如果該對象也定義了onclick屬性,則執行屬性的值。
在事件捕獲的過程中:事件首先會交給最外層的元素,接着再交給更具體的元素。
在事件冒泡中:當事件發生時,會首先發送給最具體的元素,在這個元素獲得響應機會之後,事件會向上冒泡至更一般的元素。事件冒泡有時候會産生副作用,導緻始料不及的行為。
那麼,什麼浏覽器采用的是“事件捕獲”模式,而又有哪些采用的是“事件冒泡”模式呢?
其實,最終出台的DOM标準規定應該同時使用這兩種政策:首先,事件要從一般到具體進行捕獲,钴,事件再通過冒泡傳回DOM樹的頂層。而事件處理可以注冊到這個過程中的任何一部分。即,可以把事件處理程式注冊到事件捕獲階段,也可以注冊到事件冒泡階段。
jQuery為了提供跨浏覽器的一緻性,它始終會在冒泡階段注冊事件處理程式。是以,我們總可以假定最具體的元素會首先獲得響應事件的機會。
二、阻止事件冒泡
<html>
<head>
<title>Porschev---Jquery事件冒泡</title>
<scriptsrc="jquery-1.3.2-vsdoc.js"type="text/javascript"></script>
</head>
<body>
<div id="divOne" οnclick="alert('我是最外層');">
<div id="divTwo" οnclick="alert('我是中間層!')">
<a id="hr_three"href="http://www.baidu.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="http://www.baidu.com" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" οnclick="alert('我是最裡層!')">點選我</a>
</div>
</div>
</body>
</html>
上面這個頁面, 分為三層:divOne是第外層,divTwo中間層,hr_three是最裡層;
他們都有各自的click事件,最裡層a标簽還有href屬性的預設行為。
運作頁面,點選“點選我”,會依次彈出:我是最裡層---->我是中間層---->我是最外層---->然後再連結到百度.
這就是事件冒泡,本來我隻點選ID為hr_three的标簽,但是确執行了三個alert操作。
事件冒泡過程(以标簽ID表示):hr_three---->divTwo---->divOne。從最裡層冒泡到最外層。
以下有四種阻止冒泡方法:
1.event.stopPropagation();
<scripttype="text/javascript">
$(function(){
$("#hr_three").click(function(event){
event.stopPropagation();
});
});
<script>
再點選“點選我”,會彈出:我是最裡層,然後連結到百度
作用是:事件處理過程中,阻止了事件冒泡,但不會阻擊預設行為(它就執行了超連結的跳轉)
2.return false;
<pre name="code" class="html"><scripttype="text/javascript">
$(function(){
$("#hr_three").click(function(event){
return false;
});
});
<script>
再點選“點選我”,會彈出:我是最裡層,但不會執行連結到百度頁面
作用是:事件處理過程中,阻止了事件冒泡,也阻止了預設行為(比如剛才它就沒有執行超連結的跳轉)
3.event.preventDefault();
<scripttype="text/javascript">
$(function(){
$("#hr_three").click(function(event){
event.preventDefault();
});
});
<script>
點選“點選我”,會發現它依次彈出:我是最裡層---->我是中間層---->我是最外層,但最後卻沒有跳轉到百度
作用是:事件處理過程中,不阻擊事件冒泡,但阻擊預設行為(它隻執行所有彈框,卻沒有執行超連結跳轉)
4.event.tatget==this
<scripttype="text/javascript">
$(function(){
<pre name="code" class="html"> $("#divOne").click(function(event){
if(event.tatget==this){
//執行
}
});
$("#divTwo").click(function(event){
if(event.tatget==this){
//執行
}
});
$("#hr_three").click(function(event){ if(event.tatget==this){
//執行
} });});<script>
再點選“點選我”,會彈出:我是最裡層,然後連結到百度
作用是:事件處理過程中,阻止了事件冒泡,但不會阻擊預設行為,event.target屬性儲存着發生事件的目标元素,隻有在真正的目标元素觸發事件時才執行操作。
注:一個事件起泡對應觸發的是上層的同一事件
特殊:如果two設定成輕按兩下事件,那麼在你單擊two的時候就會起泡觸發one單擊的事件(輕按兩下包含單擊)。