面试题答案
一键面试实现思路
- 事件委托:利用事件冒泡原理,将鼠标悬停事件绑定在一个较高层级的静态父元素上。这样,无论元素是初始存在还是动态加载的,只要它们在该父元素内,事件都会被捕获处理。
- 事件筛选:在事件处理函数中,通过检查事件目标(
event.target
)是否是我们想要添加悬停事件的特定元素,来决定是否执行相应的操作。
核心代码
假设我们要为具有class
为target - class
的元素添加鼠标悬停事件,并且存在一个静态的父元素parent - element
:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF - 8">
<title>事件委托示例</title>
</head>
<body>
<div id="parent - element">
<div class="target - class">初始存在的元素</div>
<!-- 动态加载的元素将添加在此处 -->
</div>
<script>
const parentElement = document.getElementById('parent - element');
parentElement.addEventListener('mouseover', function (event) {
if (event.target.classList.contains('target - class')) {
// 处理鼠标悬停事件
console.log('鼠标悬停在目标元素上');
}
});
// 模拟AJAX动态加载元素
setTimeout(() => {
const newElement = document.createElement('div');
newElement.classList.add('target - class');
newElement.textContent = '动态加载的元素';
parentElement.appendChild(newElement);
}, 2000);
</script>
</body>
</html>
可能遇到的性能问题及优化方案
- 性能问题:
- 事件处理函数执行频繁:如果父元素内元素众多,每次鼠标移动都会触发事件处理函数,导致性能开销较大。
- 事件筛选复杂:当需要筛选的条件复杂时,例如根据多个
class
或者特定的元素层级结构筛选,事件处理函数内的判断逻辑会增加计算量。
- 优化方案:
- 减少事件处理函数计算量:在事件处理函数内尽量避免复杂的计算和DOM操作。可以将一些计算提前,或者将常用的判断结果缓存起来。
- 精确筛选:尽可能精确地定位需要绑定事件的元素,减少不必要的筛选。例如,如果知道特定元素在DOM结构中的位置比较固定,可以利用更具体的选择器来缩小筛选范围,而不是仅依赖
class
。 - 防抖或节流:对于鼠标移动这种高频事件,可以使用防抖(debounce)或节流(throttle)技术。防抖是在事件触发后,等待一定时间(如200毫秒),如果这段时间内事件没有再次触发,才执行处理函数;节流则是规定在一定时间间隔内,事件处理函数只能执行一次。例如使用lodash库中的
debounce
或throttle
方法来优化。
import _ from 'lodash';
const parentElement = document.getElementById('parent - element');
const debouncedHandler = _.debounce(function (event) {
if (event.target.classList.contains('target - class')) {
console.log('鼠标悬停在目标元素上');
}
}, 200);
parentElement.addEventListener('mouseover', debouncedHandler);