1、事件绑定和事件冒泡
封装一个公用的事件绑定器
传入的函数会有个event,event.target是这个触发的dom元素
event.preventDefault()是阻止默认行为
event.stopPropagation()是阻止冒泡
让事件在捕获阶段发生可以给addEventListener的第第三个参数传入true,这样这个事件就可以在捕获阶段发生
先捕获在冒泡
<body>
<button id="btn">按钮</button>
<div>
<div id="n1">
你好
</div>
<div id="n2">
Hello
</div>
</div>
<script>
//公用的事件绑定器
function bindEvent(ele,type,fn,opt){
ele.addEventListener(type,fn,opt)
}
let btn = document.getElementById('btn')
bindEvent(btn,'click',e=>{
//阻止按钮的默认行为
e.preventDefault()
console.log('点击了按钮')
})
let n1 = document.getElementById('n1')
let n2 = document.getElementById('n2')
let body = document.body
bindEvent(body,'click',e=>{
console.log('body')
//默认是true让他在捕获阶段发生,不发就是false
},true)
bindEvent(n1,'click',e=>{
//阻止冒泡的行为
e.stopPropagation()
console.log('阻止冒泡')
})
bindEvent(n2,'click',e=>{
console.log('不阻止冒泡')
})
</script>
</body>
事件冒泡的应用场景是事件代理,冒泡是基于DOM树型结构的
2、什么是事件代理(事件委托)?
事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
<body>
<div id="ok">
<a href="#">1</a>
<a href="#">2</a>
<a href="#">3</a>
<a href="#">4</a>
<button id="btn">go</button>
</div>
<script>
function bindEvent(ele,type,fn,){
ele.addEventListener(type,fn)
}
let btn = document.getElementById('btn')
bindEvent(btn,'click',event=>{
event.preventDefault()
console.log('btn')
})
let ok = document.getElementById('ok')//获取父元素,利用冒泡吧事件绑定在子元素上
bindEvent(ok,'click',event=>{
event.preventDefault()
if(event.target.nodeName === 'A'){//防止子元素button触发事件
console.log('a')
}
})
</script>
</body>
3、编写一个通用的事件监听函数
考虑用不用事件代理
同target.matches来判断绑定的元素是不是需要监听的元素
考虑到函数的this指向,用call改变this指向为target
function bindEvent(elem,type,selector,fn){
if(fn == null){
fn = selector
selector = null
}
elem.addEventListener(type,event=>{
let target = event.target
if(selector){
if(target.matches(selector)){
fn.call(target,event)
}
}else{
fn.call(target,event)
}
})
}
//完整用法
let ok = document.getElementById('ok')
bindEvent(ok,'click','a',function() {
alert(this.innerHTML)
})
//普通用法
bindEvent(ok,'click',function(e) {
const target = e.target
if(target.nodeName === 'A') {
alert(target.innerHTML)
}
})