JS 事件梳理
大约 3 分钟
首先明晰定义,事件是用户和浏览器之间的交互行为,比如鼠标点击、鼠标移动、键盘按下等。
绑定事件不是绑定事件本身而是绑定事件的处理函数。因为这些事件是元素本身就有的能力,只有处理函数是我们后续添加进去的,绑定的是事件的反馈。
事件 ➕ 事件的反馈就是前端交互。
如何绑定事件的处理函数
直接绑定
内联事件监听器:
<button onclick="alert('hello')">点击我</button>
但是这种方法不推荐使用,因为这样就写死了,推荐用句柄方式绑定:
const oBtn = document.querySelector('button') oBtn.onclick = function () { alert('hello') }
这种方法的优点是兼容性好,但是缺点是只能绑定一个事件,如果有多个事件处理函数,则后面的事件会覆盖前面的事件处理函数。
事件监听
// 获取元素 const btn = document.querySelector('button') // 绑定事件 const clickEvent = function () { alert('hello') } btn.addEventListener('click', clickEvent)
addEventListener
是 W3C 规范,优点是可以绑定多个事件处理函数,缺点是兼容性不好,ie9 以下不兼容。事件代理
// 获取元素 const ul = document.querySelector('ul') // 绑定事件 ul.addEventListener('click', function (e) { // 判断点击的元素 if (e.target.tagName.toLowerCase() === 'li') { alert('hello') } })
ie8 及以下的绑定方法:
element.attachEvent('onclick', eventHandler)
。现在已经淘汰了,不做介绍。
事件流
事件流描述的是从页面中接收事件的顺序。
事件冒泡:事件开始由最具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。
事件捕获:不太具体的节点更早接收到事件,而最具体的节点最后接收到事件。
踩坑点: addEventListener
的第三个参数不为对象时是useCapture
表示是否使用捕获,默认为 false,表示事件冒泡。当为 true 时,为捕获事件。
值得注意的是事件绑定的先后顺序,都是先捕获后冒泡。像洋葱层级一样。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件绑定</title>
<style>
.wrapper {
position: relative;
width: 500px;
height: 500px;
background-color: red;
}
.outer {
position: absolute;
left: 500px;
width: 300px;
height: 300px;
background-color: blue;
}
.inner {
position: absolute;
left: 300px;
width: 100px;
height: 100px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="outer">
<div class="inner"></div>
</div>
</div>
<script>
// 事件绑定
// 1. 获取元素
const wrapper = document.querySelector('.wrapper')
const outer = document.querySelector('.outer')
const inner = document.querySelector('.inner')
const clickEvent = function clickEvent(box) {
return function () {
console.log(box + '被点击了')
}
}
// 2. 绑定事件
wrapper.addEventListener('click', clickEvent('bubble wrapper'), true)
outer.addEventListener('click', clickEvent('bubble outer'), true)
inner.addEventListener('click', clickEvent('bubble inner'), true)
wrapper.addEventListener('click', clickEvent('wrapper'), false)
outer.addEventListener('click', clickEvent('outer'), false)
inner.addEventListener('click', clickEvent('inner'), false)
</script>
</body>
</html>
如上代码,当点击最小里层黄色方块时,结果为:
wrapper被点击了
outer被点击了
inner被点击了
bubble inner被点击了
bubble outer被点击了
bubble wrapper被点击了
先从外向内捕获,再由内向外冒泡。
Loading...