父容器监听子元素mouseover/mouseout:mouseout功能异常问题
事件委托下mouseover/mouseout的精准触发解决方案
问题根源
当前mouseout逻辑的问题出在两点:
- 只判断
e.target是否带over-hotspot类,但鼠标在hotspot内部子元素间移动时,e.target是子元素而非hotspot本身,导致条件不成立 - 没区分「鼠标移出hotspot到外部」和「鼠标在hotspot内部元素间切换」这两种场景
修正后的完整代码
JavaScript
var holder = document.querySelector('.holder') holder.addEventListener('mouseover', function(e) { const hotspot = e.target.closest('.hotspot') if (hotspot && !hotspot.classList.contains('over-hotspot')) { console.log('-------------- over hotspot') hotspot.classList.add('over-hotspot') } }) holder.addEventListener('mouseout', function(e) { const hotspot = e.target.closest('.hotspot') if (hotspot && hotspot.classList.contains('over-hotspot')) { // 用relatedTarget判断鼠标是否真的离开hotspot区域 const isTrulyLeaving = !hotspot.contains(e.relatedTarget) if (isTrulyLeaving) { console.log('-------------- out hotspot') hotspot.classList.remove('over-hotspot') } } })
CSS(无需修改)
.hotspot { background: red; display: inline-block; margin: 10px; } .hotspot p {} .foo { width: 50px; height: 50px; background: blue; position: relative; }
HTML(无需修改)
<div class="holder"> <div class="hotspot"> <p>some text</p> <div class="foo"></div> </div> </div>
核心修改说明
- 统一通过
e.target.closest('.hotspot')获取目标hotspot,减少重复DOM查询 - 在mouseout事件中,利用
hotspot.contains(e.relatedTarget)做关键判断:- 如果
relatedTarget不在hotspot范围内,说明鼠标确实移出了hotspot,才执行移出逻辑 - 如果
relatedTarget是hotspot的子元素,说明只是内部移动,不触发mouseout操作
- 如果
这样就能实现需求:仅在鼠标进出hotspot时各触发一次事件,内部移动不会误触发。
内容的提问来源于stack exchange,提问作者Toniq
相关产品推荐
相关产品推荐

