面试题答案
一键面试设计思路
- 使用事件委托:将事件处理程序绑定到父元素上,利用事件冒泡机制,减少事件处理函数的绑定数量,从而提升性能。例如,如果有多个菜单按钮,将点击事件绑定到菜单的父容器上,而不是每个按钮都绑定。
- 正确处理
this
上下文:使用addEventListener
的第三个参数({passive: true}
用于提高滚动性能,此处不涉及滚动可不考虑),并在事件处理函数内部通过事件目标来确定实际触发事件的元素。可以使用Object.defineProperty
来创建一个新的对象,在这个对象上定义事件处理函数,这样可以在函数内部通过this
访问到这个对象上的数据。 - 避免频繁创建函数实例:将通用的事件处理逻辑封装成一个函数,根据不同的事件类型和元素类型进行逻辑分发,而不是为每个元素都创建一个新的函数实例。
关键代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="menu">
<button data-menu-type="item1">菜单选项1</button>
<button data-menu-type="item2">菜单选项2</button>
</div>
<form id="myForm">
<input type="text" name="username" data-form-field="username">
<input type="submit" value="提交">
</form>
<script>
const menuData = {
item1: '菜单选项1的数据',
item2: '菜单选项2的数据'
};
const formData = {
username: '初始用户名'
};
const handleEvent = function(event) {
const target = event.target;
if (target.closest('#menu button')) {
const menuType = target.dataset.menuType;
console.log(`点击了菜单选项 ${menuType},数据为:`, menuData[menuType]);
} else if (target.closest('#myForm input')) {
const formField = target.dataset.formField;
if (target.type ==='submit') {
console.log('提交表单,用户名:', formData.username);
} else {
formData[formField] = target.value;
console.log('输入框值改变,新值为:', formData[formField]);
}
}
};
document.addEventListener('click', handleEvent);
document.addEventListener('input', handleEvent);
</script>
</body>
</html>
在上述代码中:
- 事件委托:通过
document.addEventListener
将click
和input
事件委托给document
,这样不管是菜单按钮的点击还是表单输入框的输入事件都能被捕获。 - 处理
this
上下文:通过事件对象的target
属性来确定触发事件的具体元素,然后根据元素的dataset
属性来获取相关数据,不需要依赖this
的特定指向。 - 避免频繁创建函数实例:整个应用只使用了一个
handleEvent
函数来处理所有相关事件,根据不同的元素类型和事件类型进行逻辑分支处理。