事件捕获与事件冒泡
示例代码:
<div class="爷爷">
<div class="爸爸">
<div class="儿子">
文字
</div>
</div>
</div>
事件捕获
从外向内找监听函数,例如点击文字,先从“爷爷”的元素找触发事件,一直到“儿子”的事件完成触发。
事件冒泡
从内向外找监听函数,上面的例子反过来。
事件监听
api:addEventListener
//语法
// bool如果为true,就是捕获事件;如果是false,就是冒泡事件。如果不填或者falsy值,默认冒泡事件。
baba.addEventListener('click',fn,bool)
W3C的事件模型
先捕获(先爸爸,再儿子),再冒泡(儿子 => 爸爸)。注意,e对象会被传给所有的监听事件,当事件结束以后,e就不存在了。
target和currentTarget的区别?
- e.target是用户操作的元素;
- e.currentTarget是程序员监听的元素;
举例:
<div>
<span>文字</span>
</div>
用户点击了文字,e.target就是span,e.currentTarget就是div。
取消冒泡
方法:
// 方法
// 中断冒泡,浏览器不再向上走
e.stopPropagation()
注意:
- 所有的冒泡都可以取消,默认动作有的可以取消,有的不可以取消;
- Cancelable用来取消(也可以说是阻止)默认动作的;
阻止滚动
代码:
<style>
// 隐藏滚动条
::-webkit-scrollbar{
width:0 !important
}
</style>
<div id="x">
100个p标签
</div>
<script>
// 阻止滚轮事件
x.addEventListener('wheel',(e)=>{
e.preventDefault()
})
// 阻止手机的触屏事件
x.addEventListener('touchstart',()=>{
e.preventDefault()
})
</script>
小结:
scroll事件是不可取消冒泡的,阻止scroll的默认动作也没用,因为先用滚动,才有滚动事件。要想阻止滚动,可以阻止wheel和touchstart事件,但是滚动条还能用,可以用CSS隐藏滚动条,width:0。
自定义xxx事件
代码:
<div id="div1">
<button id="button1">点击触发xxx事件</button>
</div>
<script>
div1.addEventListener('click',()=>{
// CustomEvent就是表示自定义事件
// 1.定义事件
const event=new CustomEvent('xxx',{
detail:{name:'frank',age:18},
// 可以冒泡
bubbles:true,
// 不能阻止/取消冒泡
cancelable:false
})
// 2.触发这个自定义事件
button1.dispatchEvent(event)
})
button1.addEventListener('xxx',(e)=>{
console.log(e.detail)
})
</script>
事件委托
事件委托,就是由于性能原因或者无法获取目标元素,绑定目标元素的父元素,进行事件操作。
<div id="div1">
<button>1</button>
<button>2</button>
</div>
<script>
div1.addEventListener('click',(e)=>{
let t=e.target;
if(t.tagName.toLowerCase()==='button'){
console.log(`按钮被点击了,点击的内容是${t.textContent}`)
}
})
</script>
事件委托的优点是:
(1)不用遍历,省内存;
(2)可以监听动态元素;