1.關於js中事件的等級劃分:
(1).DOM0事件:eg:onclick等事件,直接使用dom.onclick=function(){}等,即將事件監聽掛在節點上,回調中的this直接指向當前節點;此類事件缺點是之只能爲爲節點綁定一次相同的事件:
eg:<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
eve.onclick=()=>{
console.log('點1')
}
eve.onclick=()=>{
console.log('點2')
}
</script>
</body>
運行結果只會出現點2,即第二次定義的onclick會覆蓋第一次定義的onclick
(2).DOM1:未涉及事件相關
(3).DOM2事件:eg:addEventListener('click',function(){},false)這類事件
其中最後的參數false代表冒泡階段,如果參數爲true則代表捕獲階段;
該事件綁定的有點是不會發生像DOM0事件一樣的事件覆蓋,eg:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
eve.addEventListener('click',(e)=>{
console.log('1')
})
eve.addEventListener('click',(e)=>{
console.log('2')
})
</script>
</body>
本段代碼會輸出1,2
(4).DOM3事件:eg:addEventListener('keyup',function(){},false)這類事件
從本質上說是和DOM2操作差不多的,但是新增了鼠標和鍵盤等更多類事件
2.關於事件的冒泡和捕獲
(1)事件模型:捕獲和冒泡
(2)冒泡的一個具體應用場景:想象一下現在我們有一個10列、100行的HTML表格,你希望在用戶點擊表格中的某一單元格的時候做點什麼。比如說我有一次就需要讓表格中的每一個單元格在被點擊的時候變成可編輯狀態。如果把事件處理器加到這1000個單元格會產生一個很大的性能問題,並且有可能導致內存泄露甚至是瀏覽器的崩潰。相反地,使用事件代理的話,你只需要把一個事件處理器添加到table元素上就可以了,這個函數可以把點擊事件給截下來,並且判斷出是哪個單元格被點擊了
(2)事件流:捕獲->目標階段->冒泡
(3)DOM事件捕獲的具體流程:window->document->html->body->對應dom層次->目標
冒泡的具體流程與此相反。
各節點層次在js中如何獲取:
window:window
document:document
html:docunment.documentElement
body:document.body
dom:document.getElementsID()等
現在用js代碼來具體描述捕獲的具體流程:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
window.addEventListener('click',()=>{
console.log('我是window,已經捕獲')
},true)
document.addEventListener('click',()=>{
console.log('我是document,已經捕獲')
},true)
document.documentElement.addEventListener('click',()=>{
console.log('我是html,已經捕獲')
},true)
document.body.addEventListener('click',()=>{
console.log('我是body,已經捕獲')
},true)
eve.addEventListener('click',()=>{
console.log('我是點擊目標,已經捕獲')
},true)
window.addEventListener('click',()=>{
console.log('我是window,已經冒泡')
},false)
document.addEventListener('click',()=>{
console.log('我是document,已經冒泡')
},false)
document.documentElement.addEventListener('click',()=>{
console.log('我是html,已經冒泡')
},false)
document.body.addEventListener('click',()=>{
console.log('我是body,已經冒泡')
},false)
eve.addEventListener('click',()=>{
console.log('我是點擊目標,已經冒泡')
},false)
</script>
</body>
</html>
運行結果如下:
我是window,已經捕獲
我是document,已經捕獲
我是html,已經捕獲
我是body,已經捕獲
我是點擊目標,已經捕獲
我是點擊目標,已經冒泡
我是body,已經冒泡
我是html,已經冒泡
我是document,已經冒泡
我是window,已經冒泡
3.關於自定義事件:
關於自定義事件可以有兩種定義方法
第一種就是Event
如果後面要跟參數則可以使用第二種CustomEvent
步驟:
1.let event = new Event('defineEvent')或者let event = new CustomEvent('defineEvent')//定義事件名
2.dom.addEventListener('defineEvent',()=>{},false)//添加事件監聽器
3.dom.dispatchEvent(event)//執行事件
下面就用js來實現:
<body>
<div>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
let event = new CustomEvent('defineEvent',{detail:{a:'我是參數'}})//定義事件名
eve.addEventListener('defineEvent',(e)=>{
console.log(e.detail.a)
},false)//添加事件監聽器
eve.dispatchEvent(event)//執行事件
</script>
</body>
4.關於事件event常用api
event.preventDefault()//阻止默認事件發生,比如點擊鏈接後瀏覽器會自動跳轉等
event.stopPropagation()//阻止事件冒泡到父元素
event.currentTarget//事件所綁定的元素
event.target//指的是引起事件出發的元素
event.stopImmediatePropagetion()//阻止後續綁定在相同元素上的事件觸發
eg:
<body>
<div id='hhh'>
<span id="eve">添加事件</span>
</div>
<script>
let eve = document.getElementById('eve')
let hhh = document.getElementById('hhh')
eve.addEventListener('click',(e)=>{
console.log('我是點擊目標,已經冒泡',e.currentTarget.id+':'+e.target.id+e.clientX)
e.stopImmediatePropagation()
},false)
eve.addEventListener('click',(e)=>{
console.log('我是點擊目標,已經冒泡kkkkkk',e.currentTarget.id+':'+e.target.id+e.clientX)
},false)
eve.addEventListener('mouseleave',(e)=>{
console.log('我是點擊目標,已經冒泡kkkkkk',e.currentTarget.id+':'+e.target.id+e.clientX)
},false)
只會輸出第一個事件的輸出值
</script>
event.clientX//鼠標點擊點以瀏覽器左定點爲座標原點的橫座標
event.keyCode//鍵盤操作的鍵盤碼字