本文探索一下Event的冒泡過程和初學遇到的幾個小bugjavascript
Event接口是檢測在DOM中的發生的全部事件,咱們一直在用,並且從DOM的很早的版本就一直在用着。早期的網景(後來的火狐)和IE是各自爲戰,直到W3C一統江湖,DOM版本一路發展而來,經歷了DOM-0(洪荒時代)、DOM-1(只有兩章核心內容)、DOM-2(劃時代的一個版本,咱們學的Event就在這個版本,並且目前的用的也是這個版本)、DOM-三、DOM-4(草案階段)。css
//一、有一個js函數以下
function print(){
console.log(1)
}
//二、在html的button裏面點擊觸發上面的函數
<button id=button onclick="?">點我</button>
//問號處填能夠填什麼 A. print() B.print C.print.call()
//在js裏面的onclick裏面觸發
button.onclick = ?
//問號處能夠填什麼 A. print() B.print C.print.call()
複製代碼
A
C
,第二個問號應該選B
()
的,而第二處在JS中,onclick是一個屬性,不須要馬上執行,等用戶點擊了,瀏覽器再反應,不須要()
。既然onclick
等on事件在JS中是一個屬性,那麼後面的就會覆蓋前面的,因此DOM2裏面引入了一個重要的EventListener
,是一個隊列。html
這是一個隊列,例子1,先進先出的特色,爲後面的冒泡模型作準備。java
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
remove
來實現one
執行一次的操做function f(){
console.log("eventListener不會覆蓋2")
button2.removeEventListener('click', f)
}
button2.addEventListener('click', f)
複製代碼
只會打印一次,不會一直打印了,也就是one
的原理。git
上面的官方文檔中,我只研究一下捕獲階段(capture phase)和冒泡階段(bubbling phase)。github
grand.addEventListener('click', function(){
console.log('我是你爺爺')
})
dad.addEventListener('click', function(){
console.log('我是你爸爸')
})
son.addEventListener('click', function(){
console.log('我是你兒子')
})
複製代碼
div
的事件,當你點擊的時候,控制檯打印必然會有順序。那麼應該是什麼順序呢,正常人的思惟不外乎兩種結果
grand.addEventListener('click', function(){
console.log('我是你爺爺')
}, true)
dad.addEventListener('click', function(){
console.log('我是你爸爸')
}, true)
son.addEventListener('click', function(){
console.log('我是你兒子')
}, true)
複製代碼
addEventListener
後面的參數決定了順序,當你不寫的時候是undefined
,也就是false
的意思。falsey
值
0
NaN
''
null
undefined
除此以外都是true
上圖是簡單的圖解,注意優先運行爲true
的部分,再運行false
的部分。瀏覽器
簡單的實例====================>demoapp
grand.addEventListener('click', function(){
console.log('我是你爺爺')
}, true)
dad.addEventListener('click', function(){
console.log('我是你爸爸')
})
son.addEventListener('click', function(){
console.log('我是你兒子')
複製代碼
true
,先打印誰,都是false
,繼續按照冒泡順序打印。son.addEventListener('click', function(){
console.log('我是你兒子true')
}, true)
son.addEventListener('click', function(){
console.log('我是你兒子false')
})
複製代碼
false
true
,應該打印什麼呢parent
是關鍵字不能使用,一不當心使用的話會出問題。dom
div
的display是block,點擊其餘地方變爲none。很快你會碰到了第一個bug異步
正常來講,應該點擊body控制檯打印數字1,你點爛了你的羅技鼠標也沒出來。爲何呢?
使用了紅色border以後,發現body的高度過矮了,點擊不到啊。
很好,你進入了第二個bug了
根據圖片 中的控制檯能夠發現,確實都點擊到了,監聽沒問題,並且點擊後,也是按照冒泡的順序打印的結果。
註釋掉出問題的代碼後,上圖是正常的點擊出現對話框啊,說明問題就出在註釋的代碼上。
div
,以後,往 body
document
上冒泡,在document
上馬上被殺死,display變爲none,你作夢能看到 彈出框啊。咱們既然知道了第二個bug產生的緣由,那麼咱們阻止冒泡順序
clickMe.addEventListener('click', function(){
popover.style.display = 'block'
console.log('點擊浮層了')
})
wrapper.addEventListener('click', function(e){
e.stopPropagation()
})
document.addEventListener('click', function(){
popover.style.display = 'none'
console.log('點擊文檔了')
})
複製代碼
$(clickMe).on('click', function(){
$(popover).show()
console.log('show')
setTimeout(function(){
console.log('one click')
$(document).one('click', function(){
console.log('我覺的他不會執行')
$(popover).hide()
})
},0)
})
// $(wrapper).on('click', function(e){
// e.stopPropagation()
// })
$(document).on('click', function(){
console.log('走到document啦')
})
複製代碼
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…