为何JavaScript事件委托中click生效而mouseenter不生效?
为什么mouseenter事件无法通过事件委托触发?
我通过自定义事件委托方法给父元素.a绑定了click和mouseenter事件,指定监听子元素.b,结果click事件能正常触发,但mouseenter事件完全没反应,代码如下:
HTML代码:
<div class="a"> <div class="b">this is b</div> </div>
JS代码:
const on = (element, type, selector, handler) => { element.addEventListener(type, (event) => { if (event.target.closest(selector)) { handler(event); } }); }; var a = document.querySelector('.a') on(a, 'click', '.b', (event) => console.log('click')); on(a, 'mouseenter', '.b', (event) => console.log('mouseenter'))
问题原因
核心问题在于**mouseenter和mouseleave是不冒泡的事件**,和mouseover/mouseout这类冒泡事件有本质区别:
- 当鼠标进入
.b元素时,mouseenter事件只会在.b元素自身触发,不会沿着DOM树向上传播到父元素.a; - 你的事件委托逻辑是把监听器绑定在父元素上,完全依赖事件冒泡来捕获子元素的事件触发,所以父元素的
mouseenter监听器根本不会被触发,自然无法检测到.b的触发行为。
解决方案
方案1:用mouseover替代mouseenter
mouseover是冒泡事件,能被父元素捕获,不过要额外处理它的重复触发问题(比如鼠标从.b的子元素移到.b本身时,也会触发mouseover),以此模拟mouseenter的行为:
const on = (element, type, selector, handler) => { element.addEventListener(type, (event) => { const target = event.target.closest(selector); if (target) { // 过滤掉从目标元素内部移动过来的情况,避免重复触发 if (type === 'mouseover' && event.relatedTarget && target.contains(event.relatedTarget)) { return; } handler(event); } }); }; var a = document.querySelector('.a'); on(a, 'click', '.b', (event) => console.log('click')); on(a, 'mouseover', '.b', (event) => console.log('mouseover(模拟mouseenter)'));
方案2:直接绑定到子元素
如果.b元素不是动态生成的,也可以跳过事件委托,直接给.b绑定mouseenter事件:
document.querySelector('.b').addEventListener('mouseenter', () => console.log('mouseenter'));
内容的提问来源于stack exchange,提问作者Toniq
相关产品推荐
相关产品推荐

