document的mouseover与mouseout事件多次触发:需仅触发一次
解决光标进出Document的事件触发问题
问题说明
需要实现两个事件:光标进入document时触发激活逻辑,离开document时触发取消激活逻辑。但当前使用mouseover和mouseout事件时,光标在document内部元素间移动也会频繁触发这两个事件,导致逻辑误执行。
原因分析
mouseover和mouseout是冒泡型事件,会在鼠标跨越任意元素边界时触发。当鼠标在document内的子元素间移动时,子元素的mouseout/mouseover事件会冒泡到document层面,从而导致绑定在document上的事件被误触发。
解决方案
方案一:使用mouseenter/mouseleave事件
这两个事件专为元素边界的进出场景设计:
mouseenter:仅当鼠标从目标元素(此处为document)外部进入时触发,内部元素间移动不会触发mouseleave:仅当鼠标从目标元素内部离开到外部时触发,内部移动不会触发
修改后的代码如下:
let cursor = document.getElementById('cursor'); function onMousEnter() { cursor.classList.add('is-active'); console.log("Enter!"); } function onMouseLeave() { cursor.classList.remove('is-active'); console.log("Out!"); } // 替换事件类型为mouseenter和mouseleave document.addEventListener('mouseenter', onMousEnter); document.addEventListener('mouseleave', onMouseLeave); const onMouseMove = (e) => { cursor.style.left = e.pageX + 'px'; cursor.style.top = e.pageY + 'px'; } document.addEventListener('mousemove', onMouseMove);
方案二:通过relatedTarget过滤内部事件(兼容旧场景)
如果因兼容性限制必须使用mouseover/mouseout,可以通过判断event.relatedTarget是否属于document范围,来过滤内部移动的触发:
let cursor = document.getElementById('cursor'); function onMousEnter(e) { // 仅当鼠标从document外部进入时执行逻辑 if (!document.contains(e.relatedTarget)) { cursor.classList.add('is-active'); console.log("Enter!"); } } function onMouseLeave(e) { // 仅当鼠标离开到document外部时执行逻辑 if (!document.contains(e.relatedTarget)) { cursor.classList.remove('is-active'); console.log("Out!"); } } document.addEventListener('mouseover', onMousEnter); document.addEventListener('mouseout', onMouseLeave); const onMouseMove = (e) => { cursor.style.left = e.pageX + 'px'; cursor.style.top = e.pageY + 'px'; } document.addEventListener('mousemove', onMouseMove);
内容的提问来源于stack exchange,提问作者public9nf
相关产品推荐
相关产品推荐

