点击事件
2002年,W3C 发布标准 DOM Level 2 Events Specification
规定浏览器需要同时支持两种调用顺序:
首先按照爷爷=>爸爸=>儿子的顺序看有没有函数监听
然后按儿子=>爸爸=>爷爷的顺序看有没有函数监听
有监听函数就调用,并提供事件信息,没有就跳过
从外向内找监听函数,叫做事件捕获
从内向外找监听函数,叫做事件冒泡
addEventListener
事件绑定 API
- IE5:baba.attchEvent('onclick',fn) // 冒泡
- 网景:baba.addEventListener('click',fn) // 捕获
- W3C:baba.addEventListener('click',fn,bool)
如果 bool 为 ture
- 就让 fn 走捕获,即当浏览器在捕获阶段发现 baba 有 fn 监听参数,就会调用 fn, 并提供事件信息
如果不传 bool 或者为 falsy
- 就让 fn 走冒泡,即当浏览器在冒泡阶段发现 baba 有 fn 监听参数,就会调用 fn, 并提供事件信息
代码示例
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class="level1 x">
<div class="level2 x">
</div>
</div>
</body>
</html>
css
* {
box-sizing: border-box;
}
div[class^=level] {
border: 1px solid;
border-radius: 50%;
display: inline-flex;
}
.level1 {
padding: 10px;
background: purple;
}
.level2 {
padding: 10px;
background: blue;
}
.x{
background: transparent;
}
JS
const level1 = document.querySelector('.level1')
const level2 = document.querySelector('.level2')
let n = 1
level1.addEventListener('click', (e)=>{
const t = e.currentTarget
setTimeout(()=>{
t.classList.remove('x')
},n*1000)
n+=1
})
level2.addEventListener('click', (e)=>{
const t = e.currentTarget
setTimeout(()=>{
t.classList.remove('x')
},n*1000)
n+=1
})
target 和 currentTarget
区别
- e.target - 用户操作的元素
- e.currentTarget - 程序员监听的元素
举例
- div.span{文字}
- 用户点击文字
- e.target 就是 span
- e.currentTarget 就是 div
特例
- 只有一个 div 被监听(不考虑父子同时被监听)
- fn 分别在捕获阶段和冒泡阶段监听 click 事件
- 用户点击的元素就是开发者监听的
- 这是一个特例,谁先监听谁先执行
取消冒泡
- 捕获不可取消,冒泡可以
- e.stopPropagation() 可中断冒泡,浏览器不再向上走
- 一般用来封装某些独立的组件
不可阻止默认动作
- 有些事件不能阻止默认动作
- MDN 搜索 scroll event,看到 Bubbles 和 Cancelable
- Bubbles 的意思是该事件是否冒泡,所有冒泡都可取消
- Cancelable 的意思是开发者是否可以阻止默认事件
- Cancelable 与冒泡无关
如何阻止滚动?
- scroll 事件不可阻止默认动作
- 阻止 scroll 默认动作没用,因先有滚动才有滚动事件
- 要阻止滚动,可阻止 wheel 和 touchstart 的默认动作
- 需要找准滚动条所在的元素
x.addEventListener('wheel', (e)=>{ e.preventDefault() }) x.addEventListener('touchstart', (e)=>{ e.preventDefault() })
- 但是滚动条还能用
- 可用 CSS 让滚动条 width: 0
::-webkit-scrollbar{ width:0 !important }
- 或者用 CSS 使用 overflow: hidden
- 可以直接取消滚动条,但此时JS依然可以修改 scrollTop
自定义事件
- 浏览器自带事件,一共100多种,详细列表见 MDN
- 开发者可以在自带事件之外,自定义事件
事件委托
如何给100个按钮添加点击事件?
答:监听这100个按钮的祖先,等冒泡的时候判断 target 是不是这100个按钮中的一个
如何监听目前不存在的元素的点击事件?答:监听祖先,等点击的时候看看是不是想要监听的元素
优点
- 省监听数(内存)
- 可以监听动态元素
JS 是否支持事件?
- 支持也不支持,DOM 事件不属于 JS 的功能,属于浏览器提供的 DOM 的功能
- JS只是调用了 DOM 提供的 addEventListener 而已
*本文为鲲游北冥的原创文章,著作权归本人和饥人谷所有,转载务必注明来源