理解Event的冒泡模型
本文探索一下Event的冒泡過程和初學遇到的幾個小bug
DOM Event概述
Event接口是檢測在DOM中的發生的所有事件,我們一直在用,而且從DOM的很早的版本就一直在用著。早期的網景(后來的火狐)和IE是各自為戰,直到W3C一統江湖,DOM版本一路發展而來,經歷了DOM-0(洪荒時代)、DOM-1(只有兩章核心內容)、DOM-2(劃時代的一個版本,我們學的Event就在這個版本,而且目前的用的也是這個版本)、DOM-3、DOM-4(草案階段)。
- 通過一個例子喚醒對Event的認識
- 很明顯第一個問號應該選A C,第二個問號應該選B
- 第一處在HTM中,點擊事件要立刻執行代碼,肯定選擇帶()的,而第二處在JS中,onclick是一個屬性,不需要立刻執行,等用戶點擊了,瀏覽器再反應,不需要()。
既然onclick等on事件在JS中是一個屬性,那么后面的就會覆蓋前面的,所以DOM2里面引入了一個重要的EventListener,是一個隊列。
addEventListener
這是一個隊列,例子1,先進先出的特點,為后面的冒泡模型做準備。
function f(){console.log("eventListener不會覆蓋") }button2.addEventListener('click', function(){console.log("eventListener不會覆蓋1") }) button2.addEventListener('click', f) button2.removeEventListener('click', f) button2.addEventListener('click', function(){console.log("eventListener不會覆蓋3") }) 復制代碼- 會打印出什么呢,答案是eventListener不會覆蓋1 eventListener不會覆蓋3
- 所以說既然on可以一個打印出結果,就可以借助remove來實現one執行一次的操作
只會打印一次,不會一直打印了,也就是one的原理。
- 具體的模型可以看W3C
冒泡模型
上面的官方文檔中,我只研究一下捕獲階段(capture phase)和冒泡階段(bubbling phase)。
- 什么是冒泡呢?我們先看一段代碼
- 這是三個div的事件,當你點擊的時候,控制臺打印必然會有順序。那么應該是什么順序呢,正常人的思維不外乎兩種結果
- 第一種:我是你的兒子 我是你爸爸 我是你爺爺
- 第二種: 我是你爺爺 我是你爸爸 我是你兒子
- 到底是那種呢,W3C說都行,看你代碼咋寫的了,上面的代碼打印順序是第一個中,也就是冒泡。
- 如果你想實現第二種打印方式,也就是捕獲階段,應該修改代碼如下
- 也就是說addEventListener后面的參數決定了順序,當你不寫的時候是undefined,也就是false的意思。
- 復習一下五個falsey值
- 0 NaN '' null undefined 除此之外都是true
上圖是簡單的圖解,注意優先運行為true的部分,再運行false的部分。
簡單的實例====================>demo
- 一個變式
- 上述代碼應該是什么順序呢
- 誰是true,先打印誰,都是false,繼續按照冒泡順序打印。
一個奇葩的問題
son.addEventListener('click', function(){console.log('我是你兒子true') }, true)son.addEventListener('click', function(){console.log('我是你兒子false') }) 復制代碼- 給同一個元素 false true,應該打印什么呢
- 答案是: 按照書寫的順序,誰在前面先打印誰。
意想不到的Bug
parent是關鍵字不能使用,一不小心使用的話會出問題。
- 你用了關鍵字做變量,把鼠標點爛也看不到效果。
點擊空白,對話框消失的案例
- 領導說有一個需求,點擊某個按鈕,彈出對話框,點擊空白會消失。
- 你的第一個思路:先把div設為none,點擊按鈕的時候,再讓這個div的display是block,點擊其他地方變為none。
- 很好,你去實現一下吧。
第一個bug
-
很快你會碰到了第一個bug
- 第一個錯誤:監聽錯了對象
正常來說,應該點擊body控制臺打印數字1,你點爛了你的羅技鼠標也沒出來。為什么呢?
- 我們使用border大法,看看它到底在哪
使用了紅色border之后,發現body的高度太矮了,點擊不到啊。
- 你明白監聽錯對象了,那你就換了一個對象,監聽文檔唄,肯定沒問題了。
第二個bug
-
很好,你進入了第二個bug了
- 第二個bug:你都能點擊到,但是彈不出對話框了
根據圖片 中的控制臺可以發現,確實都點擊到了,監聽沒問題,而且點擊后,也是按照冒泡的順序打印的結果。
- 那為什么沒有對話框了呢
注釋掉出問題的代碼后,上圖是正常的點擊出現對話框啊,說明問題就出在注釋的代碼上。
- bug出現的原因就在于:默認冒泡的影響,當你點擊的浮層那個div,之后,往 body document上冒泡,在document上立刻被殺死,display變為none,你做夢能看到 彈出框啊。
修復第二個bug
我們既然知道了第二個bug產生的原因,那么我們阻止冒泡順序
- 解決的方案,不讓其往上冒泡,自己管理。
- 但是隨之而來的是一個關于內存占用的問題,現在你是只有一個popover,只有一個函數,等你有了很多個popover,如果按照這個寫法會有很多個函數,所以不能這么寫,采用下面的寫法,節省內存。
- 只有點擊的時候才用,設置settimeout是為了讓他異步,不至于立刻隱藏,產生第一個bug。
- 注意一下,jQuery的 show() hide()
- 當你點擊按鈕,只會打印圖中這兩句話,另外兩句只有再次點擊才會打印。
JS版本的節省內存的版本==================>節省內存
jQuery版本的節省內存版本=================>jQuery節省內存
對話框小三角的制作
.popover{display: inline-block;border: 1px solid red;position: relative;padding: 10px;margin:10px; } .popover::before{position: absolute;content: '';top: 5px;right: 100%;border: 10px solid transparent;border-right-color:red; } .popover::after{content: '';border: 10px solid transparent;position: absolute;right: 100%;top: 5px;border-right-color: white;margin-right: -1px; } 復制代碼主要利用boder-right-color以及兩個偽元素。
浮層三角的實例=============================>demo
冒泡的直觀體現
點擊一下會有驚喜的github.com/codevvvv9/b…
冒個泡
總結
以上是生活随笔為你收集整理的理解Event的冒泡模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 墨墨背单词如何测词汇量
- 下一篇: Centos7 安装mongodb记录