移除元素所有事件監聽_DOM 事件模型或 DOM 事件機制

DOM 事件模型

DOM 的事件操作(監聽和觸發),都定義在EventTarget接口。所有節點對象都部署了這個接口,其他一些需要事件通信的瀏覽器內置對象(比如,XMLHttpRequest、AudioNode、AudioContext)也部署了這個接口。

該接口主要提供三個實例方法。

  • addEventListener:綁定事件的監聽函數
  • removeEventListener:移除事件的監聽函數
  • dispatchEvent:觸發事件

事件模型

一個事件發生后,會在子元素及父元素之間進行傳播(propagation),這種傳播分為三個階段。

(這種三階段的傳播模型,使得同一個事件會在多個節點上觸發。)

    1. 由外向內找監聽函數就是事件捕獲
    2. 在目標節點觸發事件
    3. 由內而外找監聽函數就是事件冒泡

通俗一點來說就是一個事件被觸發時,瀏覽器會自動從用戶操作標簽外的最上級標簽逐漸向里檢查是否有相同事件,如果有則觸發,如果沒有則繼續向下檢查知道用戶操作的標簽,這過程稱為捕獲,此時瀏覽器會繼續由用戶操作標簽繼續向是上級標簽檢查,如果有相同事件則觸發,如果沒有則繼續向上檢查直到最上級元素為止,此過程稱為冒泡。(有監聽函數就執行,并提供事件信息,沒有就跳過)

事件傳播的最上層對象是window,上例的事件傳播順序,在捕獲階段依次為window、document、html、body、父節點、目標節點,在冒泡階段依次為目標節點、父節點、body、html、document、window。

DOM事件傳播的三個階段:捕獲階段,目標階段,冒泡階段

點擊事件

代碼:

<div class="grandfather"><div class="father"><div class="son"></div>word</div>
</div>

即.grandfather>.father>.son

給三個div分別添加事件的監聽fnYe/fnBa/fnEr

提問1:點擊了誰?

點擊文字,算不算點擊兒子?

點擊文字,算不算點擊爸爸?

點擊文字,算不算點擊爺爺?

答案:都算

提問2:調用循序

點擊文字,最先調用fnYe/fnBa/fnEr中的那一個函數?

答案:都行

IE5認為先調用fnEr,網景認為先調用fnYe,最后遇到了W3C

2002年,w3c發布標準
文檔名為DOM Level 2 Events Specification
規定瀏覽器應該同時支持兩種調用順序
首先按照grandfather->father->son
然后按照son->father->grandfather

術語:

從外向內找監聽函數,叫做事件捕捉
從內向外找監聽函數,叫做事件冒泡
那豈不是fnYe/fnBa/fnEr都調用兩次,非也!
開發者可以自己決定把fnYe放在捕捉階段還是放在冒泡階段

5f4c06474c3e36a92c2f2c78556b3f64.png

addEventListener事件綁定API

IE5*:baba.attachEvent('onclick',fn)//冒泡

網景:baba.addEventListener('click',fn)//捕獲

W3C:baba.addEventListener('click',fn,bool)

如果bool不傳或為falsy

就讓fn走冒泡,即當瀏覽器在冒泡階段發現baba有fn監聽函數,就會調用fn,并提供時間信息。

如果bool為true

就讓fn走捕獲,即當瀏覽器在捕獲階段發現baba有fn監聽函數,就會調用fn,并且提供事件信息。

c2116c00ae986bafbd441af619a3749e.png

代碼演示:

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title>
</head>
<body>
<div class="level1 x"><div class="level2 x"><div class="level3 x"><div class="level4 x"><div class="level5 x"><div class="level6 x"><div class="level7 x"></div></div></div></div></div></div>
</div></body>
</html>

CSS:

* {box-sizing: border-box;
}
div[class^=level] {border: 1px solid;border-radius: 50%;display: inline-flex;
}
.level1 {padding: 10px;background: purple;
}
.level2 {padding: 10px;background: blue;
}
.level3 {padding: 10px;background: cyan;
}
.level4 {padding: 10px;background: green;
}
.level5 {padding: 10px;background: yellow;
}
.level6 {padding: 10px;background: orange;
}
.level7 {width: 50px;height: 50px;border: 1px solid;background: red;border-radius: 50%;
}
.x{background: transparent;//把元素的變為透明
}

Javascript代碼:

const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
const level3 = document.querySelector('.level3')
const level4 = document.querySelector('.level4')
const level5 = document.querySelector('.level5')
const level6 = document.querySelector('.level6')
const level7 = document.querySelector('.level7')let n = 1level1.addEventListener('click', (e)=>{const t = e.currentTarget//e只有在點擊得一瞬間才會出現,所以要用t來記錄一下。setTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1//因為如果每個時間都為1000那么就相當于在8點同時設置很多的鬧鐘,。知識
})
level2.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level3.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level4.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level5.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level6.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})
level7.addEventListener('click', (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
})

簡化:

const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
const level3 = document.querySelector('.level3')
const level4 = document.querySelector('.level4')
const level5 = document.querySelector('.level5')
const level6 = document.querySelector('.level6')
const level7 = document.querySelector('.level7')let n = 1const fm = (e)=>{const t = e.currentTargetsetTimeout(()=>{  t.classList.remove('x')},n*1000)n+=1
}const fa = (e)=>{const t =e.currentTargetsetTimeout(()=>{t.classList.add('x')},n*1000)n+=1}level1.addEventListener('click',fm,true)
level1.addEventListener('click',fa)
level2.addEventListener('click',fm,true)
level2.addEventListener('click',fa)
level3.addEventListener('click',fm,true)
level3.addEventListener('click',fa)
level4.addEventListener('click',fm,true)
level4.addEventListener('click',fa)
level5.addEventListener('click',fm,true)
level5.addEventListener('click',fa)
level6.addEventListener('click',fm,true)
level6.addEventListener('click',fa)
level7.addEventListener('click',fm,true)
level7.addEventListener('click',fa)

知識復習:

classList:

定義和用法

classList 屬性返回元素的類名,作為 DOMTokenList 對象。

該屬性用于在元素中添加,移除及切換 CSS 類。

classList 屬性是只讀的,但你可以使用 add() 和 remove() 方法修改它。

HTML DOM classList 屬性?www.runoob.com

currentTarget 事件屬性

定義和用法

currentTarget 事件屬性返回其監聽器觸發事件的節點,即當前處理該事件的元素、文檔或窗口。
在捕獲和起泡階段,該屬性是非常有用的,因為在這兩個節點,它不同于 target 屬性。

currentTarget ê??tê?D??www.w3school.com.cn

總結:

兩個疑問:

兒子被點擊,算不算點擊老子?

那么先調用老子得函數還是先調用兒子的函數?

捕獲冒泡

捕獲說先調用爸爸的監聽函數

冒泡說先調用兒子的監聽函數

W3C時間模型

先捕獲(先爸爸=>兒子)再冒泡(再兒子=>爸爸)

注意e對象被傳給所有的監聽函數

事件結束后,e對象就不存在了

target v.s. currentTarget的區別

區別:

e.target - 用戶操作的元素
e.currentTarget-程序員監聽的元素
this是e.currentTarget,我個人不推薦使用它

舉例:

div>span{文字},用戶點擊文字
e.target就是span
e.currentTarget就是div

一個特例

背景:

只有一個div被監聽(不考慮父子同時被監聽)

fn分別再捕獲階段和冒泡階段監聽click事件

用戶點擊的元素就是開發者監聽的

代碼:

div.addEventListenter('click',f1)

div.addEventListenter('click',f2,true)

請問,f1先執行還是f2先執行?

如果把兩個調換位置?

總結:誰先監聽誰先執行。

level7.addEventListener('click',()=>{console.log(2)
},true)//捕獲
level7.addEventListener('click',()=>{console.log(1)
})//冒泡

e.stopPropagation():取消冒泡

e.stopPropagation()可打斷冒泡,瀏覽器不再向上走

一般用于封裝某些獨立組件

注意:捕獲不可以取消但是冒泡可以

不可以取消冒泡

有些事件不可以取消冒泡

可以查閱MDN英文版冒泡

比如scroll:

a3f78b9f7ecaf71eeb642ddbc658611b.png

Bubbles:冒泡

Cancelable:是否取消冒泡

如何禁用滾動

取消特定元素的wheel和touchstart的默認動作

JS Bin?js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

瀏覽器自帶事件

來自MDN:

事件參考?developer.mozilla.org
04a10667cec1221014320944799dba8f.png

自定義事件:代碼

JS Bin?js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

5a6336f11d64a8a22e2a2916176537a2.png

事件委托:

我委托一個元素幫我監聽我本該監聽的東西,比如onclick

場景1:

要給100個按鈕添加點擊事件,咋辦?

答:監聽這個100個按鈕的祖先,等冒泡的時候判斷target是不是這100個按鈕中的一個

代碼:

JS Bin?js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

場景2:

你要監聽目前不存在的元素的點擊事件?

答:監聽祖先,等點擊的時候看看是不是監聽的元素即可。

優點:省監聽數(內存),可以動態監聽元素

代碼:

JS Bin?js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

封裝一個事件委托

只要實行一個函數就可以實現事件委托

要求:

寫出這樣一個函數on('click','#testDiv','li',fn)

當用戶點擊#testDiv里面的li元素時,調用fn函數

要求用到事件委托

答案1:判斷target是否匹配'li'

答案2:target/target的爸爸/target的爺爺

代碼:

JS Bin?js.jirengu.com
458783ef3f4c9d676cfebe3ab8409077.png

錯的但是面試可以用:

答:給一個元素加一個監聽,看當前的target是否滿足監聽函數(函數2)中函數2的條件如果滿足調用,不滿足放過。但是是錯的!

代碼:

setTimeout(()=>{const button = document.createElement('button')const span = document.createElement('span')span.textContent='click 1'button.appendChild(span)div1.appendChild(button)
},1000)on('click','#div1','button',()=>{//'#div'是選擇器不是元素console.log('button 被點擊啦')
})
function on(eventType,element,selector,fn){if(!(element instanceof Element)){element = document.querySelector(element)}element.addEventListener(eventType,(e)=>{const t= e.target//被點擊的元素是span不是button啦if(t.matches(selector)){//matches用來判斷一個元素是否匹配一個選擇器,selector是不是一個選擇器
span不匹配buttonfn(e)}
})
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/541565.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/541565.shtml
英文地址,請注明出處:http://en.pswp.cn/news/541565.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gettimezone_Java日歷getTimeZone()方法與示例

gettimezone日歷類的getTimeZone()方法 (Calendar Class getTimeZone() method) getTimeZone() method is available in java.util package. getTimeZone()方法在java.util包中可用。 getTimeZone() method is used to return this Calendar time zone. getTimeZone()方法用于返…

cass展點不在原位置_cass展點之步驟及方法

cass展點之步驟及方法cass展點是根據手工或坐標正反算軟件自動計算的結果&#xff0c;利用cass軟件將點號、坐標及其高程自動展示到圖紙上的一種方法。其基本步驟和方法如下&#xff1a;一、將井下測點的點號、以及計算好的Y坐標、X坐標、及高程由sheet1復制并粘貼到sheet2上面…

Java BufferedWriter close()方法與示例

BufferedWriter類close()方法 (BufferedWriter Class close() method) close() method is available in java.io package. close()方法在java.io包中可用。 close() method is used to flushes the characters from the stream and later will close it by using close() metho…

ISCC2014-reverse

這是我做reverse的題解。在咱逆向之路上的mark一下&#xff0c;&#xff0c;水平有限&#xff0c;大牛見笑。題目及題解鏈接&#xff1a;http://pan.baidu.com/s/1gd3k2RL 宗女齊姜 果然是僅僅有50分的難度&#xff0c;OD直接找到了flag. 找到殺手 這題用OD做非常麻煩。我改用I…

python 獲取當前時間再往前幾個月_Python 中的時間和日期操作

Python中,對日期和時間的操作,主要使用這3個內置模塊: datetime 、 time 和 calendar 獲取當前時間對應的數字 開發程序時,經常需要獲取兩個代碼位置在執行時的時間差,比如,我們想知道某個函數執行大概耗費了多少時間,就可以使用time.time()來做。 import time before =…

Java BigDecimal restder()方法與示例

BigDecimal類的restder()方法 (BigDecimal Class remainder() method) Syntax: 句法&#xff1a; public BigDecimal remainder(BigDecimal divsr);public BigDecimal remainder(BigDecimal divsr, MathContext ma_co);remainder() method is available in java.math package.…

python程序需要編譯么_python需要編譯么

一個經常聽見的問題&#xff0c;那就是&#xff1a;Python是解釋型的語言嗎&#xff1f;它會被編譯嗎&#xff1f;這個問題沒有想象中那么好回答。和很多人認識世界一樣&#xff0c;習慣以一個簡單的模型去評判一些事物。而事實上&#xff0c;里面包含了很多很多的細節。通常的…

DevOps平臺中的自動化部署框架設計

本文目錄&#xff1a; 一、背景 二、我們的需求是什么&#xff1f; 三、概念澄清 四、概念模型 五、總體設計 六、關鍵點設計 七、總結 一、背景 說到自動化部署&#xff0c;大家肯定都會想到一些配置管理工具&#xff0c;像ansible,chef,puppet, saltstack等等。雖然這些工具給…

插入排序算法 ,遞歸實現_C程序實現遞歸插入排序

插入排序算法 ,遞歸實現The only difference between Insertion sort and Recursive Insertion Sort is that in the Recursive method, we start from placing the last element in its correct position in the sorted array instead of starting from the first. 插入排序和…

python虛擬機直接加載字節碼運行程序_第二章 python如何運行程序

一.python解釋器介紹Python解釋器是一種讓程序運行起來的程序。實際上&#xff0c;解釋器是代碼與機器的計算機硬件之間的軟件邏輯層。當Python包安裝在機器上后&#xff0c;它包含了一些最小化的組件&#xff1a;一個解釋器和支持的庫。二.python的視角當Python運行腳本時&…

Java LocalDate類| 帶示例的format()方法

LocalDate類format()方法 (LocalDate Class format() method) format() method is available in java.time package. format()方法在java.time包中可用。 format() method is used to format this LocalDate object by using the given DateTimeFormatter object. format()方法…

胃癌2019csco指南_2019 CSCO胃癌診療指南精華來了!

一文輕松get 2019 CSCO胃癌診療指南更新要點&#xff01;文丨青青子衿 中山大學腫瘤防治中心來源丨醫學界腫瘤頻道近日&#xff0c;2019年CSCO指南發布會于南京召開。今天為大家推送的是2019 CSCO胃癌診療指南的最新更新&#xff0c;在發布專場中&#xff0c;來自華中科技大學同…

001_docker-compose構建elk環境

由于打算給同事分享elk相關的東西,搭建配置elk環境太麻煩了,于是想到了docker。docker官方提供了docker-compose編排工具,elk集群一鍵就可以搞定,真是興奮。好了下面咱們開始吧。 一、 https://github.com/deviantony/docker-elk $ cd /006_xxxallproject/005_docker/001_e…

Java即時類| toString()方法與示例

即時類toString()方法 (Instant Class toString() method) toString() method is available in java.time package. toString()方法在java.time包中可用。 toString() method is used to represent this Instant as a String by using the standards ISO-8601 format. toString…

learn opengl 中文_LearnOpenGL CN

歡迎來到OpenGL的世界歡迎來到OpenGL的世界。這個工程只是我(Joey de Vries)的一次小小的嘗試&#xff0c;希望能夠建立起一個完善的OpenGL教學平臺。無論你學習OpenGL是為了學業&#xff0c;找工作&#xff0c;或僅僅是因為興趣&#xff0c;這個網站都將能夠教會你現代(Core-p…

MYSQL5.7 日志管理

2019獨角獸企業重金招聘Python工程師標準>>> 慢查詢日志slow-query-log1 slow-query-log-filefile_name long_query_time1 #SQL執行多長時間以上會記錄到慢查詢日志&#xff0c;0~10s log_slow_admin_statementsOFF #在寫入慢查詢日志的語句中包含緩慢的管理語句。 …

duration java_Java Duration類| ofHours()方法與示例

duration javaDuration Class of Hours()方法 (Duration Class ofHours() method) ofHours() method is available in java.time package. ofHours()方法在java.time包中可用。 ofHours() method is used to represent the given hours in this Duration. ofHours()方法用于表示…

sumo的簡單應用_sumo快速運行簡單仿真實例詳細教程

本文旨在讓大家快速的了解sumo&#xff0c;并給出運行一個簡單的sumo的例子的教程&#xff0c;進而了解基本sumo工程的架構&#xff0c;使大家對該軟件產生興趣并持續學習下去&#xff0c;剛開始學習仿真的確枯燥&#xff0c;項目“跑起來”才是大家學習下去的動力&#xff0c;…

stl vector 函數_vector :: crbegin()函數,以及C ++ STL中的示例

stl vector 函數C vector :: crbegin()函數 (C vector::crbegin() function) vector::crbegin() is a library function of "vector" header, it is used to get the last element of a vector using const_reverse_iterator, it returns a const reverse iterator …

ReactNative學習筆記(二)Flex布局

flexDirection 決定主軸方向 column&#xff1a;垂直方向為主軸row:水平方向為主軸justifyContent 決定主軸元素排列方式 flex-startflex-endcenterspace-betweenspace-aroundalignItems 決定側軸元素排列方向 flex-startflex-endcenterbaselinestretch