天天看點

JQuery事件冒泡機制與解決

一、什麼是事件冒泡?

       當一個事件發生的時候,該事件總是有一個事件源,即引發這個事件的對象,一個事件不能憑空産生,這就是事件的發生。

當事件發生後,這個事件就要開始傳播。為什麼要傳播呢?因為事件源本身并沒有處理事件的能力。例如我們點選一個按鈕時,就會産生一個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單擊的事件(輕按兩下包含單擊)。

繼續閱讀