摘要:事件冒泡一個簡單,但是坑了我無數回的知識點與的交互通過事件來實現。而瀏覽器的事件流是一個非常重要的概念。不去討論那些古老的瀏覽器有事件捕獲與事件冒泡的爭議,只需要知道在中規(guī)定的事件流包括了三個部分,事件捕獲階段處于目標階段事件冒泡階段。
打算封裝一個彈窗組件,做的時候忘記了考慮事件冒泡的因素,結果被坑得不要不要的。為了解決自己的問題,去查閱了不少資料,把事件流相關的知識都給總結一下。
事件冒泡:一個簡單,但是坑了我無數回的知識點!
JavaScript與HTML的交互通過事件來實現。而瀏覽器的事件流是一個非常重要的概念。不去討論那些古老的瀏覽器有事件捕獲與事件冒泡的爭議,只需要知道在DOM2中規(guī)定的事件流包括了三個部分,事件捕獲階段、處于目標階段、事件冒泡階段。
一、事件捕獲事件捕獲,是從document元素開始,越高級的父級元素越早接收到事件,因此這是一個從上而下的過程。
還是那句話,沒在實際應用中踩過坑,可能你真的不算掌握了這個知識點。那么,事件捕獲有什么常見的坑呢?
可能不少同學在初學js的時候遇到過這樣一個坑。一個ul元素中初始的狀態(tài)有4個li元素,我們可以循環(huán)給li元素添加click事件,執(zhí)行我們想要的動作。這個例子的坑就在于,新添加的li元素不會有我們綁定的click事件。
是的,就是這么坑,為了解決這個問題,我們就要利用事件捕獲的原理。
$("ul.container").click(function(event) { var target = event.target; if (target.className == "item") { // dosomething } })
在上面的解決方案中,我并不是直接給li綁定事件,而是給所有l(wèi)i的父級ul綁定事件。根據事件捕獲的原理,事件會自上而下傳遞給li,我們只需要通過一些簡單的條件判斷來確定我們的目標元素即可,如上例中的判斷l(xiāng)i的className。
這個方式就是大名鼎鼎的事件委托。
事件委托是一個很重要而且在實際中會常常用到的知識點。
當我們在使用className判斷目標元素時,會遇到這樣的情況。
...
xxxxxxs
...當我們試圖使用事件委托希望給所有的li添加元素時,在利用className判斷的過程中發(fā)現,目標event.target元素居然是li.item的子元素,這個時候就沒辦法準確的將事件綁定到li上了,這個時候我們應該怎么辦?
這種情況,我們要做的,就是阻止事件捕獲的傳遞,那么,要如何阻止呢?
我知道的一種方式,利用css,給li所有子元素添加如下css屬性即可
li.item > * { pointer-events: none; }
按道理來說,應該是有js方式的,可是查了很多文章都沒有提及,因此就暫時這樣吧,到時候遇到了在補充。
在jquery中,已經幫助我們實現了事件委托,并且?guī)臀覀兘鉀Q掉了這些坑。我們只需要按照一定語法使用即可,而我們不用再自己去進行條件判斷,比如我們要給所有的li.item元素綁定事件,寫法如下
// on中的第二參數就是我們的目標元素的選擇器 $("ul.container").on("click", "li.item", function(event) { // dosomething })二、事件冒泡
說完了事件捕獲,然后來說說事件冒泡這個坑。所謂事件冒泡,就是讓DOM樹最底層的目標元素最先接收到事件,然后往上傳遞,這是一個自下而上的過程。
我們常常會遇到一種彈窗樣式,彈窗出來時,內容在中間,然后會有一層半透明的遮罩將頁面內容與彈窗區(qū)分開。彈窗內容會有一些按鈕綁定點擊事件,比如確認與取消。而在半透明遮罩上,可能也會綁定一個點擊事件,當點擊時,將彈窗隱藏。如果我由于經驗不足,將該遮罩層設置成了彈窗按鈕的父級,那么就會遇到事件冒泡帶來的麻煩。
也就是說,在如下例子中 container是全屏遮罩,button是彈窗里面的點擊按鈕。他們都同時綁定了click事件,執(zhí)行不同的動作。但是在實際執(zhí)行的時候,當我點擊了button,那么button和container的click事件都會執(zhí)行,自下而上按順序執(zhí)行
click
我為這個事情寫了一個小例子,大家可以動手感受一下這個坑。點擊空白會生成一個彈窗
http://yangbo5207.github.io/s...
好吧解決問題的方法很簡單,就是阻止冒泡事件。
$xxx.click(function(e) { e.stopPropagation(); // ie e.cancelBubble = true; })
理解了整個事件流,我們可以感受事件在DOM中的傳遞過程與方向,并且利用他來解決我們的問題和各種坑,雖然是一個簡單的知識點,但是卻非常容易被忽略,因此建議大家找機會將它掌握牢固。
而還有一個坑,可能大家在實際中會很少遇到,這個坑就是,某些事件類型天生就不支持事件冒泡!
blur: 在元素失去焦點時觸發(fā),該事件不支持冒泡
focus: 在元素獲得焦點時觸發(fā),該事件不支持冒泡
mouseenter: 當鼠標移入元素時觸發(fā),該事件不支持冒泡
mouseleave: 當鼠標移出元素時觸發(fā),該事件不支持冒泡
... ...
以及IE6 IE7 IE8中 的 change、select、submit、reset 事件事實上都沒有參照規(guī)范定義產生事件冒泡。
當你在需要的冒泡的時候,綁定了這些事件,而你恰好不知道居然還有事件天生就不支持冒泡的,那么你可能就悲劇了。所以這個點只要在腦袋里面有個印象就好了,我只記得我曾經遇到過這樣一個坑,但暫時想不起來應用場景了 - -!
我所知道的,遇到過的關于事件流的坑就這么多了,想來應該也算是非常完整的一個總結了,值得大家點一下推薦和收藏的哦!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49871.html
摘要:事件冒泡一個簡單,但是坑了我無數回的知識點與的交互通過事件來實現。而瀏覽器的事件流是一個非常重要的概念。不去討論那些古老的瀏覽器有事件捕獲與事件冒泡的爭議,只需要知道在中規(guī)定的事件流包括了三個部分,事件捕獲階段處于目標階段事件冒泡階段。 打算封裝一個彈窗組件,做的時候忘記了考慮事件冒泡的因素,結果被坑得不要不要的。為了解決自己的問題,去查閱了不少資料,把事件流相關的知識都給總結一下。 ...
摘要:在之前是只支持事件冒泡,包括之后和目前主流的瀏覽器都同時支持兩種事件。中可以用來取消事件冒泡。 剛接觸 JS 的那個時候,啥也不懂,只想著如何利用 Google、百度到的函數來解決實際的問題,不會想到去一探究竟。 漸漸的,對 JS 的語言的不斷深入,有機會去了解一些原理性東西。最近在看 JQuery 源碼,感觸很多,總想著用原生的 JS 去實現自己的一個 JQuery 庫。說實在的,J...
摘要:若時間差大于間隔時間,則立刻執(zhí)行一次函數。不同點函數防抖,在一段連續(xù)操作結束后,處理回調,利用和實現。函數防抖關注一定時間連續(xù)觸發(fā)的事件只在最后執(zhí)行一次,而函數節(jié)流側重于一段時間內只執(zhí)行一次。 原博客地址,歡迎star 函數防抖和節(jié)流 函數防抖和函數節(jié)流:優(yōu)化高頻率執(zhí)行js代碼的一種手段,js中的一些事件如瀏覽器的resize、scroll,鼠標的mousemove、mouseover...
閱讀 2031·2023-04-25 15:24
閱讀 1575·2019-08-30 12:55
閱讀 1615·2019-08-29 15:27
閱讀 470·2019-08-26 17:04
閱讀 2406·2019-08-26 10:59
閱讀 1797·2019-08-26 10:44
閱讀 2193·2019-08-22 16:15
閱讀 2587·2019-08-22 15:36