事件与事件流
事件,这里指和网页进行互动。比如点击链接,移动鼠标等网页被触发,做出响应,形成交互。
js 采用事件监听器来监听事件是否发生。
事件流
事件流描述了从页面中接收事件的顺序。当一个事件发生在某个元素上时,它会沿着元素层次结构向上传播或向下传播,这就是事件流。事件流分为冒泡阶段和捕获阶段。
事件冒泡流
事件冒泡是指事件从最具体的元素开始(例如用户点击的按钮),然后逐级向上传播至最不具体的节点(例如 document
)(现在某些浏览器会一直冒泡到 window 对象)。在事件冒泡过程中,事件会逐级触发每个父元素的相同事件,进而触发这些事件对应的处理函数。
事件捕获流
事件捕获与事件冒泡相反,事件从最不具体的节点开始(例如 document
),然后逐级向下传播至最具体的节点(例如用户点击的按钮)。在事件捕获过程中,事件会逐级触发每个祖先元素的相同事件,进而触发这些事件对应的处理函数。
标准 DOM 事件流
标准 DOM 事件流包括三个阶段:
- 捕获阶段: 事件从
window
对象开始,逐级向下传播至目标元素。 - 目标阶段: 事件到达目标元素,触发目标元素上绑定的事件处理函数,此时事件才会发生并处理,而且本次事件处理会被看成是冒泡阶段的一部分。
- 冒泡阶段: 事件从目标元素开始,逐级向上传播至
window
对象(某些浏览器)。
事件委托(事件代理)
事件委托,又被称之为事件代理。在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面整
体的运行性能。导致这一问题的原因是多方面的。
首先,每个函数都是对象,都会占用内存。内存中的对象越多,性能就越差。其次,必须事先指定所有事件
处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。
对事件处理程序过多问题的解决方案就是事件委托。
事件委托利用了事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。例如,click事件会
一直冒泡到document层次。也就是说,我们可以为整个页面指定一个onclick事件处理程序,而不必给每个
可单击的元素分别添加事件处理程序。
优点:
- 只用在父元素上绑定相应事件,绑定的事件更少,页面的效率更高
- 子元素的兄弟元素事件不用重复添加
<body>
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
<script>
// 目标:为 li 添加点击事件
// const lis = document.getElementsByTagName('li')
// for (let i = 0; i < lis.length; i++) {
// lis[i].onclick = function () {
// console.log('li 触发点击事件')
// }
// }
// 使用事件委托来优化代码
const ul = document.getElementById('ul')
ul.onclick = function (event) {
if (event.target.nodeName === 'LI') {
console.log('li 触发点击事件')
}
}
</script>
</body>