1. 程式人生 > >jsDOM獲取元素方法、事件委託、事件捕獲和事件冒泡

jsDOM獲取元素方法、事件委託、事件捕獲和事件冒泡

本篇博文解決的問題:

1、給父元素註冊點選事件,特定子元素響應該點選事件;——2.2 事件委託

2、給父元素註冊點選事件,點選父元素,所有子元素響應/不響應該點選事件;——2.3 事件冒泡

3、給子元素和父元素註冊點選事件,點選子元素,自己有點選事件的父元素響應/不響應自己的點選事件。——2.3 事件冒泡

4、給多個子元素和父元素註冊點選事件,點選子元素,只響應子元素的點選事件。——2.2 事件委託 2.3 事件冒泡

一 示例

       要求:根據以下程式碼,在<script>標籤中新增程式碼,刪除一條資料。

       下面程式碼中可以看出新增的程式碼必須使用js的原生方式,DOM獲取元素的方法有getElementById、getElementsByName、getElementsByTagName和getElementByClassName。

       若根據id來獲取元素並新增點選事件,由於只有父元素具有id,因此點選事件新增在父元素上,子元素“刪除”進行響應,則需要用到事件委託:通過父元素給子元素註冊點選事件。 

       提供的程式碼為:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <!--code here-->
  <title>demo</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    .head, li div {
      display: inline-block;
      width: 70px;
      text-align: center;
    }

    li .id, li .sex, .id, .sex {
      width: 15px;
    }

    li .name, .name {
      width: 40px;
    }

    li .tel, .tel {
      width: 90px;
    }

    li .del, .del {
      width: 15px;
    }

    ul {
      list-style: none;
    }

    .user-delete {
      cursor: pointer;
    }

  </style>
</head>

<body>
  <div id="J_container">
    <div class="record-head">
      <div class="head id">序號</div><div class="head name">姓名</div><div class="head sex">性別</div><div class="head tel">電話號碼</div><div class="head province">省份</div><div class="head">操作</div>
    </div>
    <ul id="J_List">
      <li><div class="id">1</div><div class="name">張三</div><div class="sex">男</div><div class="tel">13788888888</div><div class="province">北京</div><div class="user-delete">刪除</div></li>
      <li><div class="id">2</div><div class="name">李四</div><div class="sex">女</div><div class="tel">13788887777</div><div class="province">上海</div><div class="user-delete">刪除</div></li>
      <li><div class="id">3</div><div class="name">王五</div><div class="sex">男</div><div class="tel">13788889999</div><div class="province">天津</div><div class="user-delete">刪除</div></li>
    </ul>
  </div>

<script>
// your code here
</script>
</body>
</html>

       效果為:


       script中的程式碼為:

//方法1,直接獲取class,為刪除的div新增點選事件
var a = document.getElementsByClassName("user-delete");
for(var i = 0, len = a.length; i < len; i++) {
	a[i].addEventListener("click", function(e) {
		this.parentNode.remove();
	})
}

//方法2:點選事件新增在ul上,使用事件委託
var deletef = function() {
	this.del = function(li) {
		li.remove();
	}
}

var delli = new deletef();
var parent = document.getElementById("J_List");
parent.addEventListener("click", function(e) {
	if (e.target.className === "user-delete") {
		delli.del(e.target.parentNode);
	}
},false);

二 相關方法解釋

       在上面script中涉及到的方法有:

1、DOM獲取元素的方法

       返回一個匹配特定ID的元素,不存在則返回null。

       一般情況下認為這是一個唯一值,因此如果頁面上有多個相同id的元素,DOM只會解析第一個元素,頁面只會顯示第一個元素,則也只能獲取第一個元素。

       根據給定的“name”返回一個在HTML document的節點列表集合。

       name是元素的name屬性的值。包含添加了name自定義屬性的元素。

       在IE和Opera中,該方法還會返回id為指定值的元素,所以最好不要為元素的name和id賦同樣的值。

       返回一個包括所有給定標籤名稱的元素的HTML集合,這個檔案結構都會被搜尋,包括根結點。

       返回的HTML集合是動態的,即它可以自動更新自己來保持和DOM樹的同步而不用再次呼叫。

       使用方法:

var elements = document.getElementsByTagName(name);

       name是一個代表元素的名稱的字串。

       返回一個包含了所有指定類名的子元素的類陣列物件。當在document物件上呼叫時,會搜尋真個DOM文件,包括根結點。

       在任意元素上呼叫此方法將返回以當前元素為根結點,所有指定類名的子元素。

2、DOM事件委託

       事件委託,即把一個元素的響應事件的函式委託給另一個元素。

       一般情況下,把一個或一組元素的事件委託給它的父元素或者更外層元素上,因此真正繫結事件的是外層元素,當事件響應到需要繫結的元素上時,會通過事件冒泡機制觸發到它的外層元素的繫結事件上,然後在外層元素上進行執行。

       重新來看上面的程式碼:

var parent = document.getElementById("J_List");
parent.addEventListener("click", function(e) {
	if (e.target.className === "user-delete") {
		//真正要執行的程式碼
	}
},false);

       實際上要進行click事件響應的是li的子元素“刪除”這個div,但是在程式碼中可以看到事件繫結給了ul元素,e為點選的元素,即所繫結的外層元素,target元素是在外層元素之下具體被點選的元素,通過判斷target的屬性來進行匹配,此處是通過class來判斷找到“刪除”這個div。

       注意,程式碼中少了相容性處理:

var parent = document.getElementById("J_List");
parent.addEventListener("click", function(e) {
	//相容性處理
	var event = e || window.event;
	var target = event.target || event.srcElement;
	if (target.className === "user-delete") {
		//真正要執行的程式碼
	}
},false);
       更具體和詳細的解釋等可以看JavaScript事件委託詳解

3、DOM事件捕獲和事件冒泡

       上面提到了事件冒泡,它具體是什麼呢?

事件冒泡:當滑鼠點選或者觸發DOM事件時,瀏覽器會從內向外進行事件傳播,直到根節點。即點選了父元素,如果子元素通過事件冒泡方式註冊了對應的事件,會先觸發子元素繫結的事件。

事件捕獲:當滑鼠點選或者觸發DOM事件時,瀏覽器會從根節點開始由外到內進行事件傳播。即點選了子元素,如果父元素通過事件捕獲方式註冊了對應的事件,會先觸發父元素繫結的事件。

       可以看到這兩個的事件的響應方式正好相反,它們的行為都是事件傳播。

       DOM事件流存在三個階段:事件捕獲階段、處於目標階段、事件冒泡階段。

       DOM標準事件流的觸發先後順序為:先捕獲再冒泡。

事件冒泡

先來看一個例子:

       首先,給上面的程式碼中的每個li新增一個id

<li id = "1">code</li>
<li id = "2">code</li>
<li id = "3">code</li>

       然後給body、ul和id為1的li新增點選事件:

var parent = document.getElementById("J_List");
var child = document.getElementById("1");

document.body.addEventListener("click", function(e){
	alert("body");
}, false);
parent.addEventListener("click", function(e){
	alert("parent");
}, false);
child.addEventListener("click", function(e){
	alert("child");
}, false);

       點選第一個li,可以看到執行結果為:


       點選子元素後,事件觸發順序是從內到外的:child-parent-body。雖然只點擊了子元素,但它的所有有點選事件的父元素全都響應了,這就是事件冒泡。

       可以這樣理解:雖然只點擊了子元素li1,但li1在parent裡面,parent又在body裡面,把它們都當成有壓感的東西,壓了最上面的,那下面的也應該有感覺,有了感覺就要有相應的反應,這個反應就是響應自己的點選事件。

       如果我不想要父元素和body有反應怎麼辦呢?這就需要阻止事件傳播。修改child的程式碼:

child.addEventListener("click", function(e){
	alert("child");
	//停止事件傳播
	e.stopPropagation();
}, false);
       執行結果:


       在上面的操作中,點選了兩次,第一次點選li1,第二次點選li3,可以看到彈出的結果就不同:

       點選li1:li1有點選事件,且阻止了事件的傳播,因此只會彈出child;

       點選li3:li3沒有點選事件,進行事件傳播,傳播到ul,檢測到有點選事件,彈出parent,再進行傳播,傳播到body,檢測到有點選事件,彈出body。

       由於冒泡是從內到外,因此阻止冒泡只能阻止該元素的事件向外傳遞,所以點選li1會阻止事件傳遞。

       而點選元素的子元素,由於子元素沒有阻止事件的傳播,因此它都會冒泡到最外層元素,所以點選li3後外層元素都會響應。

       所以如果不想點選子元素後父元素的點選事件進行響應,就需要使該父元素的子元素阻止冒泡。則如果給li3增加一個監聽事件,點選li3就不會有任何反應。

var li3 = document.getElementById("3");
li3.addEventListener("click", function(e){
    e.stopPropagation();
}, false);

       那麼,如果父元素註冊了點選事件,其中的多個子元素也註冊了點選事件,我希望不論點選哪一個子元素,父元素的點選事件都不響應,應該怎麼做呢?

有兩個方法:

       方法1:子元素的點選事件寫在自己的元素上,在每個點選事件裡新增阻止冒泡事件的語句;

       方法2:使用事件委託,將所有的點選事件寫在父元素上,使用條件語句進行判斷,在最後寫上阻止冒泡事件的語句。

因此,如果部分子元素需要父元素響應自己的點選事件、部分元素不需要父元素響應自己的點選事件,也對應以下方法:

       方法1:子元素的點選事件寫在自己的元素上,根據需要決定是否新增新增阻止冒泡事件的語句;

       方法2:使用事件委託,將不需要父元素響應的點選事件寫在父元素上,使用條件語句進行判斷,在最後寫上阻止冒泡事件的語句。

       方法3:與方法2相反,不推薦。

事件捕獲

修改上面的程式碼:

//在parent後新增事件傳播,表示是事件傳播
parent.addEventListener("click", function(e){
	alert("parent事件傳播");
}, false);

//新增parent的事件捕獲,注意false變為了true
parent.addEventListener("click", function(e){
	alert("parent事件捕獲");
}, true);

執行結果:


可以看到執行順序為:parent事件捕獲-child-parent事件傳播-body。

父元素通過事件捕獲的方式註冊了click事件,根據DOM標準事件流的觸發順序,這個click事件在事件捕獲階段就會觸發,然後到了目標階段,即事件源,然後再進行事件傳播,而parent也用冒泡方式註冊了click事件,所以又會觸發冒泡事件,最後冒泡到根節點。

根據上面的程式碼可以看到,冒泡和捕獲在程式碼上的區別是監聽事件的第三個引數,第三個引數是可選引數,預設為false,即事件冒泡,當設定為true時為事件捕獲。具體使用方式看EventTarget.addEventListener()

相關推薦

jsDOM獲取元素方法事件委託事件捕獲事件冒泡

本篇博文解決的問題:1、給父元素註冊點選事件,特定子元素響應該點選事件;——2.2 事件委託2、給父元素註冊點選事件,點選父元素,所有子元素響應/不響應該點選事件;——2.3 事件冒泡3、給子元素和父元素註冊點選事件,點選子元素,自己有點選事件的父元素響應/不響應自己的點選事

jQuery——進階(動畫迴圈正則事件冒泡事件委託DOM)

目錄單標籤操作鏈式呼叫迴圈遍歷正則表示式事件冒泡事件委託建立標籤dom操作 特殊動畫效果 1.淡入淡出: fadeIn():淡入 fadeOut():淡出 fadeToggle():切換淡入淡出 2.顯示隱藏: show():顯示 hide():隱藏 togg

事件冒泡捕獲事件委託

事件冒泡與捕獲 事件冒泡:事件從觸發事件的節點開始一直向上傳播直至父節點。 事件捕獲:事件從父級節點開始一直傳遞到觸發事件的節點。 當你使用事件捕獲時,父級元素先觸發,子級元素後觸發,即div先觸發,p後觸發。 當你使用事件冒泡時,子級元素先觸發,父級元素後觸發,

Javascript之獲取元素距離頁面的topleftrightbottom

原文出處:https://blog.csdn.net/a271720559/article/details/81278345 我們在做網頁是有時會需要用到絕對定位這時需要判定元素離頁面的距離。今天我們來看看怎麼獲取元素距離頁面的top、left、right、bottom。 程式碼: va

DOM的預設事件事件模型事件委託阻止預設事件冒泡事件的方式等。

DOM0,DOM2,DOM3事件,事件基礎知識入門   事件是javascript和HTML互動基礎, 任何文件或者瀏覽器視窗發生的互動, 都要通過繫結事件進行互動;   事件有DOM0, DOM2和DOM3的區分(別問我怎麼少了一個DOM1, 也沒

JavaScript基礎(十)動畫事件委託3DBanner

動畫、事件委託、3DBanner 動畫 一個簡單的動畫 QQ客戶懸浮窗 動畫封裝 案例-Banner輪播圖 焦點淡入淡出 向上向下 向左向右 無縫自動播放

面試題-冒泡捕獲事件委託ie事件dom模型事件滑鼠事件

    一直沒有搞懂jquery中的事件是怎麼新增事件處理程式的。原來就是用了事件委託,關鍵就是通過冒泡方式實現在最高層(document)處理事件,通過判斷事件target的id,給以不同的handler。當然也可以通過事件捕獲來處理,但是因為ie中只有冒泡,所以還是用

設計模式(九)-觀察者模式C#委託事件

書中引出的例子為,當Boss回來,前臺通知員工好好工作的場景。1、觀察模式將通知廣播給每一個客戶端,客戶端想知道目標的變化a、從目標拉取 b、通知的時候將變化傳遞給客戶端。拉取的方法,客戶端自由度較高,客戶端可以根據需求拉取。觀察者通知內容豐富,客戶端需要不要更新拉取變化。耦

Jquery獲取元素方法

strong 大小寫 element tex 一個 類選擇器 ast id選擇器 選擇 Jquery 獲取元素的方法分為兩種:jQuery選擇器、jQuery遍歷函數。 1、獲取本身:  a.只需要一種jQuery選擇器 選擇器 實例 說明 #Id $(‘#

獲取元素方法與陣列

獲取元素方法: (1), 通過js的dom方法:getElementById() :根據元素的id獲取元素 (2),通過getElementsByClassName():根據元素的class獲取頁面元素; (3),通過getElementsByTagName(): 根據元素標籤的名稱獲取

jQuery中的事件冒泡事件捕獲事件追加引發的問題

近日在專案中遇到一些問題,一個是ID值唯一存在的問題,另一個便是事件的追加產生的錯誤。 關於ID值唯一存在,從id的定義來看,id代表唯一的元素,若頁面中出現多個標籤存在相同的id,那麼此時只有第一個id所在的標籤起作用,而且會多次起作用。所以若需要多個相同的

C#的委託匿名委託lambda表示式

什麼是委託:包含單個方法的委託和函式指標是相似的,不同的是,委託是面向物件的並且是型別安全的。宣告委託型別:// Declare a delegate.delegate void Del(string str);宣告委託和宣告方法差不多,兩個不通點就在於委託以:delegat

js中的事件捕獲事件冒泡,以及由事件冒泡引入的事件委託

事件模型 首先我們認識一下事件模型: 上圖轉自:https://zhuanlan.zhihu.com/p/26536815 由上圖所示,事件模型分為三個階段: 捕獲階段 目標階段 冒泡階段 在IE8及其以前,IE瀏覽器監聽事件的API為attac

c#的委託(代理)事件

一、代理 首先我們要弄清代理是個什麼東西。別讓一串翻譯過來的概念把大家搞暈了頭。有的文章把代理稱委託、代表等,其實它們是一個東西,英文表述都是“Delegate”。由於沒有一本權威的書來規範這個概念,所以現在網上對它的稱謂不一。本文我將以“代理”來稱謂Delegate。 代

javascript學習筆記(五):異常捕獲事件處理

log 類型 按鈕 輸入 button lan yellow logs 代碼 異常捕獲 Try{   發生異常的代碼塊 }catch(err){   異常信息處理 } 1 <!DOCTYPE html> 2 <html> 3 <head

事件冒泡事件捕獲事件委托

onclick .get function cli ren 技術分享 image html www <div id="parent" onclick="checkCookie()"> <div class="child" id="chil

DOM事件機制(事件捕獲事件冒泡事件委托)

使用 tar web strong 事件 所有 span click ner 內容: 1.事件復習 2.事件冒泡與事件捕獲 3.事件委托 1.事件復習 (1)事件 事件是用來處理響應的一個機制,這個響應可以來自於用戶(點擊, 鼠標移動, 滾動), 也可以來自於瀏

javascript之事件捕獲事件冒泡

1. 事件階段 事件分為三個階段:捕獲階段、目標階段和冒泡階段。 捕獲階段: 事件從文件的根節點流向目標物件節點。途中經過各個層次的DOM節點,並在各節點上觸發捕獲事件,直到到達事件的目標節

JS中的事件捕獲事件冒泡

前言 前段時間給應屆生講JS的事件,順便講了一下事件捕獲和事件冒泡是怎麼一回事兒,但是沒給他具體的例子,這裡新增一段列子,順便給菜鳥們一些具體程式碼來看看冒泡和捕獲是怎麼一回事兒。 1、

js響應事件的階段,捕獲階段,冒泡階段

        當滑鼠點選所看到的的按鈕時,其實發生了一系列的事件傳遞,可以想象一下,button實際上是被body“包裹”起來的,body是被html“包裹”起來的,html是被document“包裹”起來的,document是被window“包裹”起來的。所以,在你的滑