mouseenter事件进入带子元素容器时触发两次,如何实现单次触发?
问题原因
你遇到的mouseenter两次触发问题,核心是事件处理函数里修改了#demo的边框样式,导致元素的几何边界发生了变化:
- 初始状态下,#demo带有1px边框,鼠标停在#demo的底部边框区域时,仍属于#demo的范围,触发第一次mouseenter。
- 事件触发后,你将#demo的
borderStyle设为none,边框直接消失。由于默认盒模型(content-box)下,border不属于元素设置的height/width范围,#demo的实际占用空间会瞬间缩小——之前鼠标所在的底部边框位置,立刻变成了#demo的外部区域。 - 当鼠标继续移动到内部的#test元素时,相当于从#demo外部重新进入元素,因此触发第二次mouseenter。
解决方案
提供几种可行的解决思路:
方法1:修改盒模型,避免元素尺寸突变
把#demo的盒模型改为border-box,这样边框会被包含在设置的height/width内,修改边框样式不会改变元素的整体尺寸:
#demo { box-sizing: border-box; /* 新增该行 */ border: 1px solid gray; height: 60px; padding: 18px; }
这种方式下,即使去掉边框,#demo的整体大小保持不变,鼠标不会因为边框消失而被“移出”元素,自然不会触发第二次事件。
方法2:调整边框修改的时机或逻辑
如果不需要动态移除边框,直接删掉事件里的this.style.borderStyle = 'none';即可。如果必须修改边框,可以换个时机(比如在mouseleave事件中恢复边框),或者通过其他样式属性(如透明度)来实现视觉效果,避免改变元素的几何边界。
方法3:添加标志位,限制重复触发
给元素设置一个状态标志,确保mouseenter在短时间内只执行一次:
const main = document.querySelector('#demo'); let isEntered = false; main.addEventListener('mouseenter', function(e) { if (isEntered) return; isEntered = true; this.style.borderStyle = 'none'; console.log('enter'); }); // 在鼠标离开时重置标志,同时可选恢复边框 main.addEventListener('mouseleave', function() { isEntered = false; this.style.borderStyle = 'solid'; });
内容的提问来源于stack exchange,提问作者cyz3a5c0v1
相关产品推荐
相关产品推荐

