哪些事件不冒泡?mouseenter、mouseover 与事件委托有什么区别?
先理解原理和示例,再练习完整口述与追问。
回答要点
捕获、目标、冒泡;focus/blur 与 focusin/out;enter/leave 与 over/out;target/currentTarget/relatedTarget;原生与框架事件区分。
原理拆解
事件传播按事件自身规则执行,不是所有事件都会冒泡。focus/blur 通常不冒泡,但可使用捕获监听,或选择会冒泡的 focusin/focusout。mouseenter/mouseleave 不冒泡,强调进入离开相关区域;mouseover/mouseout 会冒泡,指针在后代之间移动也可能触发,需要结合 relatedTarget 判断是否真正跨出目标区域。scroll 与 load 等也需按具体目标和规范处理,不能背一份混杂不同环境的清单。
委托把处理器放在祖先,通过 target 找实际动作节点;currentTarget 是当前处理器所属节点。Shadow DOM、composed 以及 React 合成事件等还有额外规则,应区分讨论。
示例与推演
function delegateClick(container, onSelect) {
function handle(event) {
if (!(event.target instanceof Element)) return
const button = event.target.closest('button[data-id]')
if (button && container.contains(button)) onSelect(button.dataset.id)
}
container.addEventListener('click', handle)
return () => container.removeEventListener('click', handle)
}
点击按钮内部图标也能找到按钮,新增后代不必重新绑定。清理函数保证组件销毁后不保留外部引用。
易错点
stopPropagation 不等于 preventDefault,捕获可被监听不等于事件会冒泡。用 contains 判断还要考虑嵌套容器的业务归属。
参考回答可直接练习口述
我按事件的原生传播规则选方案:普通点击可委托,焦点用捕获或 focusin/out,进入离开关注 enter/leave 与 relatedTarget。处理器区分目标与绑定节点,并提供清理,不把框架事件行为当全部原生规则。