hover子元素时onMouseEnter事件触发异常及目标指向父元素问题
问题描述
当hover子div时,尝试阻止事件传播以避免触发父元素的事件,但遇到两个问题:
- 尽管hover的是子元素,父元素的
onMouseEnter事件却先于子元素触发 - 通过
$(this)获取的事件目标显示的是外层<div id="kingOuter">的信息,而非子<div id="kingMiddle">
控制台输出结果

代码示例
$(document).ready(function() { $(function () { var outerElement = document.createElement("div"); outerElement.id = "kingOuter"; outerElement.textContent = "King Outer"; var middleElement = document.createElement("div"); middleElement.id = "kingMiddle"; middleElement.textContent = "King Middle"; outerElement.onmouseenter = function(e){ console.log($(this)); console.log("King outer mouse enter"); } middleElement.onmouseenter = function(e){ console.log("King middle mouse enter"); } let ppp = document.getElementById('tttest'); outerElement.appendChild(middleElement); ppp.appendChild(outerElement); }); })
问题原因与解决方法
1. 父元素mouseenter先触发的原因
mouseenter事件本身不会冒泡,但鼠标从父元素外部移动到子元素上时,会先进入父元素触发mouseenter,之后才进入子元素触发对应事件——这是事件触发的顺序逻辑,并非冒泡导致。
要避免父元素在hover子元素时触发mouseenter,可以用两种方案:
- 改用
mouseover事件(该事件支持冒泡),在子元素事件中调用e.stopPropagation()阻止冒泡 - 在父元素事件回调里判断触发目标是否为自身,再执行逻辑
2. $(this)指向父元素的原因
事件回调里的this默认指向绑定事件的元素,也就是父元素kingOuter,这是正常的绑定逻辑。如果要获取实际触发事件的目标,应该使用e.target而非this。
修正后的代码示例
$(document).ready(function() { $(function () { var outerElement = document.createElement("div"); outerElement.id = "kingOuter"; outerElement.textContent = "King Outer"; var middleElement = document.createElement("div"); middleElement.id = "kingMiddle"; middleElement.textContent = "King Middle"; // 改用mouseover并判断触发目标 outerElement.onmouseover = function(e){ // 仅当触发目标是父元素自身时执行逻辑 if(e.target === this){ console.log($(this)); console.log("King outer mouse enter"); } } middleElement.onmouseover = function(e){ console.log("King middle mouse enter"); // 阻止冒泡,避免父元素mouseover触发 e.stopPropagation(); } let ppp = document.getElementById('tttest'); outerElement.appendChild(middleElement); ppp.appendChild(outerElement); }); })
若坚持使用mouseenter,可以配合mouseleave监听鼠标位置实现,但逻辑更复杂,优先推荐上述mouseover方案。
内容的提问来源于stack exchange,提问作者Yeo Bryan
相关产品推荐
相关产品推荐

