1. 程式人生 > >淺談JS事件冒泡

淺談JS事件冒泡

       今天要跟大家談的是事件冒泡,這個事件呢,也是兩面性的,有時候給我們帶來bug,有時候優點也很明顯。我們就一起來看看它的真面目。

 首先看看事件冒泡是什麼?

 事件冒泡 :當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window 。(注意這裡傳遞的僅僅是事件 並不傳遞所繫結的事件函式。所以如果父級沒有繫結事件函式,就算傳遞了事件 也不會有什麼表現 但事件確實傳遞了。)

只看這句話,或許不是那麼好理解,下面來看個栗子:

var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
   div2.onclick 
= function(){alert(1);}; div1.onclick = function(){alert(2);};//父親 //html程式碼 <div id="div1"> <div id="div2"></div> </div>

程式碼很簡單,就是兩個父子關係的div,然後分別加了點選事件,當我們在div2裡面點選的時候,會發現彈出了一次1,接著又彈出了2,這說明點選的時候,不僅div2的事件被觸發了,它的父級的點選事件也觸發了,這種現象就叫做冒泡。點選了div1,自己父級的點選事件也會被觸發。

再看個栗子

var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2")  

div1.onclick = function(){alert(2);}; // 父親
//html程式碼 <div id="div1"> <div id="div2"></div> </div>

大家可以看一下效果圖,相比於第一個例子,程式碼已經把兒子的點選事件去掉,只留下了父級的,測試的結果是當只點擊了兒子,會彈出2,由此證明了當點選了兒子,父親的點選事件被觸發,執行了自己繫結的函式。由於一些人會以為顯示出來兒子在父親裡面的時候,自然點了兒子相當於點了父親,所以這個例子我故意把兩個盒子絕對定位在了兩個不同的位置,所以點選事件給頁面顯示出來的位置是沒關係的,而是跟html程式碼中的位置有關係。

可能有人會有疑惑下面這種情況,為啥沒有彈出兩次:

var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
   div2.onclick = function(){alert(1);}; 
   div1.onclick = function(){};  //父親

//html程式碼

 <div id="div1">

    <div id="div2"></div>

 </div>

這裡我們要注意,我們傳遞的僅僅是事件觸發,也就是說當點選div2僅僅觸發了父級的點選事件,並沒有把自己的繫結的函式給父級,父級的執行情況,取決於自己所繫結的函式,因為在這裡它繫結的函式是空,自然沒什麼表現。有些人在這裡有誤解,所以強調一下。

以上大概就是冒泡的形式了,而大多數時候,冒泡也帶來了一些困擾,下面我們看一個栗子:

我們的需求是點選上面紅色的面板讓下面粉色的面板顯示,點選其他地方再讓粉絲面板隱藏。於是我們會這樣寫js程式碼:

<script>
var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1");

  div2.onclick = function(){   //紅色面板事件
        div1.style.display = "block"; 
  };
 document.onclick = function(){ 
    div1.style.display = "none"; 
 }
</script>

這個時候我們測試發現,怎麼點選紅色面板,粉絲面板都不會顯示了,為什麼呢?就是冒泡的原因,我們來分析下程式碼,當點選div2的時候,他會觸發父親級別的點選事件,然後一層一層的往上傳,所以document的點選事件自然也被觸發了,然後執行了自己身上的繫結事件,讓粉色面板消失。所以當你點選div2的時候首先,讓粉絲面板顯示,只是事件執行太快了,很快又執行了document的點選事件,讓面板隱藏。 有興趣的可以再兩個事件之間加一個彈出,就可以測試。

那麼這個時候我們肯定不希望有冒泡了,所以解決辦法就是取消冒泡了:(後來補充)

 取消事件冒泡有兩種方式:

標準的W3C 方式:e.stopPropagation();這裡的stopPropagation是標準的事件物件的一個方法,呼叫即可

非標準的IE方式:ev.cancelBubble=true;  這裡的cancelBubble是 IE事件物件的屬性,設為true就可以了

通常我們會封裝這樣一個函式:

function stopBubble(e) {
    //如果提供了事件物件,則這是一個非IE瀏覽器
   if ( e && e.stopPropagation )
      //因此它支援W3C的stopPropagation()方法
      e.stopPropagation();
  else
  //否則,我們需要使用IE的方式來取消事件冒泡
    window.event.cancelBubble = true;
}

這個時候需要用到事件物件裡的 cancelBubble屬性,把它設為true即可,ev.cancelBubble=true;所以改進後的程式碼如下:<script>

var div2 = document.getElementById("div2");
var div1 = document.getElementById("div1");

 div2.onclick = function(ev){  // 紅色面板加事件
     div1.style.display = "block";
stopBubble(ev);//這樣就不會再冒泡給父級了
};
document.onclick = function(){
div1.style.display = "none";
}
function stopBubble(e) {
    //如果提供了事件物件,則這是一個非IE瀏覽器
   if ( e && e.stopPropagation )
      //因此它支援W3C的stopPropagation()方法
      e.stopPropagation();
  else
  //否則,我們需要使用IE的方式來取消事件冒泡
    window.event.cancelBubble = true;
}

 其實冒泡還有一大優點,就是事件委託,而且經常用到,還能提高很大的效能,想要了解,看下篇部落格嘍,我們沐晴,下回不見不散。

相關推薦

JS事件冒泡

       今天要跟大家談的是事件冒泡,這個事件呢,也是兩面性的,有時候給我們帶來bug,有時候優點也很明顯。我們就一起來看看它的真面目。  首先看看事件冒泡是什麼?  事件冒泡 :當一個元素接收到事件的時候 會把他接收到的事件傳給自己的父級,一直到window 。(注意這裡傳遞的僅僅是事件 並不傳遞所

js事件監聽

重新 參數 .com 代碼 事件類型 獲得 rem 過程 技術 淺談js事件監聽 1、在談事件監聽之前,先來了解一下什麽是js事件? 大家都知道js是一種動態數據類型的語言, 可以使我們在原有的靜態頁面上實現一些動態的效果;當網頁中的某個元素產生可以觸發js代碼(函數)實現

js冒泡事件1

prev form 定義 ati 鏈接 baidu 有一種 事件冒泡 function 什麽是JS事件冒泡?: 在一個對象上觸發某類事件(比如單擊onclick事件),如果此對象定義了此事件的處理程序,那麽此事件就會調用這個處理程序,如果沒有定義此事件處理程序或者事件返回t

js事件preventDefault()和addEventListener()

js中有許多預設事件方法,當我們觸發時就會自動執行,比如點選連結跳轉,右鍵彈出屬性選單等等。於是為了滿足我們自定義的行為,需要阻止事件預設行為,即preventDefault()方法。 preventDefault() preventDefault()是

js中的MVC

模擬 ner end i++ 反饋 mov 構架 als 觀察 MVC是什麽? MVC是一種架構模式,它將應用抽象為3個部分:模型(數據)、視圖、控制器(分發器) 本文將用一個經典的例子todoList來展開 一個事件發生的過程(通信單向流動): 1、用戶在視圖V上與應用

js 事件冒泡事件捕獲

nodename 瀏覽器兼容 而不是 rop 希望 bubble lis 彈出 element 一、事件冒泡 事件冒泡是指在事件發生過程中先從目標節點開始執行,並一層一層的相父節點依次查詢直到document,並執行相同事件的過程。 btn1.addEventListe

JS的繼承

log || prot 收獲 是我 ron col 函數 一個   JS繼承     繼承是OO語言中最為人津津樂道的概念,許多OO語言都支持兩種方式的繼承:接口繼承;實現繼承。        接口繼承:只繼承方法簽名。        實現繼承:繼承實際的方法。    

js數據類型識別方法

簡單 string name bject 識別方法 ber true logs 對象 js有5種基本數據類型 Undefined , Null , Boolean , Number , String 和一種引用類型Object,下面我們就來一一看穿,哦不,識別他們。

js本地圖片預覽

.get url 添加圖片 doc let 圖片上傳 獲取 gin radi   最近在工作中遇到一個問題,就是實現一個反饋頁面,這個反饋頁面的元素有反饋主題、反饋類型、反饋內容、反饋人聯系電話以及反饋圖片。前端將這些反饋的元素POST給後臺提供的接口;實現這個工作的步驟就

js閉包

訪問 itl js閉包 程序 學習內容 blank 學習 路線 對象   閉包是js學習中的一個重要知識點,那麽js閉包是什麽?   Js閉包就是一個函數。但是這個函數與js眾一般的函數又有一點不同,不同之處在於閉包能夠獲取其他函數體內的變量。這裏簡單回顧一下js中有關變量

JS基礎與內置對象

null ngs 但是 了解 ray 修改 創建 ror 嚴格 第一篇js文章,今天我將從基礎部分,以及三座大山開始淺談一下自己對js的理解,有不對的地方,請大神們告知修改 我們先來了解一下js的一些基礎, 首先是數據類型,JS有兩種數據類型,原始類型和引用類型,我們用ty

js設計模式之發布 — 命令模式

刪除 常見 設計程序 體會 span 一個 發送 正在 是什麽 命令模式最常見的應用場景是:有時候需要向某些對象發送請求,但是並不知道請求的接收者是誰,也不知道被請求的操作是什麽。此時希望用一種松耦合的方式來設計程序,使得請求發送者和請求接收者能夠消除彼此之間的耦合關系。

js設計模式 — 享元模式

func 參數 如何 del 如果 性能優化 情況 under 核心 享元(flyweight)模式是一種用於性能優化的模式,“fly”在這裏是蒼蠅的意思,意為蠅量級。享元模式的核心是運用共享技術來有效支持大量細粒度的對象。 假設有個內衣工廠,目前的產品有 50種男式內衣和

JS中的閉包

不能 程序 含義 函數 刪除 今天 func 空間 而且   今天 大年初一,祝各位小夥伴們狗年旺旺啊,閑來也沒事,只能鉆研一下自己的分內之事,也就是作為一個前端碼農的身份,得時刻保持學習的態度,溫故而知新,每天都給自己一個小目標去完成,日積月累,所想達到的狀態,都會有所見

JS事件冒泡事件捕獲

border 綁定 tab 現在 cells 一次 tel 加載 adding 他們是描述事件觸發時序問題的術語。事件捕獲指的是從document到觸發事件的那個節點,即自上而下的去觸發事件。相反的,事件冒泡是自下而上的去觸發事件。綁定事件方法的第三個參數,就是控制事件觸發

js的sort()方法

blog pos 最終 後者 ray 轉換 多條件 pre ole 如果調用該方法時沒有使用參數,將按字母順序對數組中的元素進行排序,說得更精確點,是按照字符編碼(字符串Unicode碼點)的順序進行排序。要實現這一點,首先應把數組的元素都轉換成字符串(如有必要),以便進行

37.js原型的理解

技術 理論 名詞 dev cnblogs 面向對象 ocs scrip cto 淺談Js原型的理解 一、js中的原型毫無疑問一個難點,學習如果不深入很容易就暈了! 在參考了多方面的資料後,發現解釋都太過專業,對於很多還沒有接觸過面向對象 語言的小白來

JS中的!=、== 、!==、===的用法和區別 JS中Null與Undefined的區別 讀取XML文件 獲取路徑的方式 C#中Cookie,Session,Application的用法與區別? c#反射 抽象工廠

main 收集 data- 時間設置 oba ase pdo 簡單工廠模式 1.0 var num = 1; var str = ‘1‘; var test = 1; test == num //true 相同類型 相同值 te

這可能是最簡明扼要的 js事件冒泡機制+阻止默認事件 講解了

不支持 自身 eve font def back 綁定 向上 版本 哎 js事件冒泡機制和阻止冒泡 阻止默認行為好像永遠也整不清楚,記了忘 忘了記。。。醉了 這篇文章寫完以後下次再忘記 就呼自己一巴掌,忘一次一巴掌   首先要明白兩個概念——事件和事件流   事件指的

JS的執行

中新 聲明 let i++ iss tor 調用 原來 階段 作用域:   作用域鏈:     子作用域能訪問父級作用域的變量和方法。父集卻不能訪問子集作用域的變量和方法    變量聲明提升:     js執行的時候會分為兩個階段:(JS的預編譯 與