我在绝对定位的div中的onmouseout函数遇到了麻烦。当鼠标击中div中的子元素时,mouseout事件发生,但我不希望它发生,直到鼠标离开父元素,绝对div。
我如何防止mouseout事件从发射时,它击中一个子元素没有jquery。
我知道这与事件冒泡有关,但我没有找到如何解决这个问题的方法。
我在这里找到了一个类似的帖子:如何禁用由子元素触发的鼠标退出事件?
但是,该解决方案使用jQuery。
我在绝对定位的div中的onmouseout函数遇到了麻烦。当鼠标击中div中的子元素时,mouseout事件发生,但我不希望它发生,直到鼠标离开父元素,绝对div。
我如何防止mouseout事件从发射时,它击中一个子元素没有jquery。
我知道这与事件冒泡有关,但我没有找到如何解决这个问题的方法。
我在这里找到了一个类似的帖子:如何禁用由子元素触发的鼠标退出事件?
但是,该解决方案使用jQuery。
当前回答
如果出于某种原因你不想使用mouseenter和mouseleave事件,你可以使用mouseover/mouseout和一些“deboundation”。
这个想法依赖于这样一个事实,即当您的事件处理程序在跨越各个子元素....之间的边界时将接收out,然后接收一个新的over除非鼠标真的离开(超过反弹周期)。这似乎比在每个事件上爬行dom节点更简单。
如果你在假设你有一个真正的out之前有一个短暂的延迟“debounce”,你可以有效地忽略所有这些从子元素冒出来的out/over事件。
注意!如果子元素也有over和/或out事件的监听器,并且它们的处理程序调用event. stoppropagation()来阻止事件向附加处理程序的父元素冒泡,这将不起作用。如果您控制代码,这并不一定是问题,但您应该注意到这一点。
示例代码
javascript
function mouseOverOutDebounce (element, debounceMs, mouseOverFn, mouseOutFn) {
var over = false,
debounceTimers = [];
function mouseOver (evt) {
if (over) { // already OVER, existing interaction
while (debounceTimers.length > 0) { // then we had a pending mouseout(s), cancel
window.clearTimeout(debounceTimers.shift());
}
}
else { // new OVER
over = true;
mouseOverFn(evt);
}
}
function mouseOut (evt) {
if (!over) return; // already OUT, ignore.
debounceTimers.push(window.setTimeout(function () {
over = false;
mouseOutFn(evt);
}, debounceMs));
}
function removeEventListeners () {
element.removeEventListener('mouseover', mouseOver);
element.removeEventListener('mouseout', mouseOut);
}
element.addEventListener('mouseover', mouseOver);
element.addEventListener('mouseout', mouseOut);
return removeEventListeners;
}
var someEl = document.querySelector('.container'),
textarea = document.querySelector('textarea'),
mouseOver = function (evt) { report('mouseOVER', evt); },
mouseOut = function (evt) { report('mouseOUT', evt); },
removeEventListeners = mouseOverOutDebounce(someEl, 200, mouseOver, mouseOut);
function report(msg, data) {
console.log(msg, data);
textarea.value = textarea.value + msg + '\n';
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
html, body {
margin: 0;
padding: 0;
}
body {
margin: 5%;
}
.container {
width: 300px;
height: 600px;
border: 10px solid red;
background-color: #dedede;
float: left;
}
.container .square {
width: 100px;
height: 100px;
background-color: #2086cf;
margin: -10px 0 0 -10px;
}
textarea {
margin-left: 50px;
width: 800px;
height: 400px;
background-color: #464646;
font-family: monospace;
color: white;
}
.bar {
width: 2px;
height: 30px;
display: inline-block;
margin-left: 2px;
background-color: pink;
}
</style>
</head>
<body>
<div class="container">
<div class="square"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>
<textarea></textarea>
<script src="interactions.js"></script>
</body>
</html>
小提琴
https://jsfiddle.net/matp/9bhjkLct/5/
其他回答
简单地,我们可以检查e.relatedTarget是否有子类,如果为真则返回函数。
if ($(e.relatedTarget).hasClass("ctrl-btn")){
return;
}
这是为我工作的代码,我用于html5视频播放,暂停按钮切换悬停视频元素
element.on("mouseover mouseout", function(e) {
if(e.type === "mouseout"){
if ($(e.relatedTarget).hasClass("child-class")){
return;
}
}
});
我认为Quirksmode有你需要的所有答案(不同的浏览器冒泡行为和mouseenter/mouseleave事件),但我认为最常见的结论是,事件冒泡混乱的使用框架,如JQuery或Mootools(有mouseenter和mouseleave事件,这正是你直觉会发生的)。
看看他们是怎么做的,如果你想的话,自己做吧 或者你也可以用事件部分(及其依赖项)创建自定义的“精益”版本的Mootools。
我检查原始元素的偏移量以获得元素边界的页面坐标,然后确保只有当鼠标退出超出这些边界时才触发鼠标退出操作。很脏,但很管用。
$(el).live('mouseout', function(event){
while(checkPosition(this, event)){
console.log("mouseovering including children")
}
console.log("moused out of the whole")
})
var checkPosition = function(el, event){
var position = $(el).offset()
var height = $(el).height()
var width = $(el).width()
if (event.pageY > position.top
|| event.pageY < (position.top + height)
|| event.pageX > position.left
|| event.pageX < (position.left + width)){
return true
}
}
我找到了一个很简单的解决办法,
只需使用onmouseleave="myfunc()"事件,而不是onmousout="myfunc()"事件
在我的代码中,它工作了!!
例子:
<html>
<head>
<script type="text/javascript">
function myFunc(){
document.getElementById('hide_div').style.display = 'none';
}
function ShowFunc(){
document.getElementById('hide_div').style.display = 'block';
}
</script>
</head>
<body>
<div onmouseleave="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
Hover mouse here
<div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
CHILD <br/> It doesn't fires if you hover mouse over this child_div
</div>
</div>
<div id="hide_div" >TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>
mouseout函数的示例:
<html>
<head>
<script type="text/javascript">
function myFunc(){
document.getElementById('hide_div').style.display = 'none';
}
function ShowFunc(){
document.getElementById('hide_div').style.display = 'block';
}
</script>
</head>
<body>
<div onmouseout="myFunc()" style='border:double;width:50%;height:50%;position:absolute;top:25%;left:25%;'>
Hover mouse here
<div id='child_div' style='border:solid;width:25%;height:25%;position:absolute;top:10%;left:10%;'>
CHILD <br/> It fires if you hover mouse over this child_div
</div>
</div>
<div id="hide_div">TEXT</div>
<a href='#' onclick="ShowFunc()">Show "TEXT"</a>
</body>
</html>
希望能有所帮助。
对于在大多数情况下都有效的更简单的纯CSS解决方案,可以通过将子指针事件设置为none来删除它们
.parent * {
pointer-events: none;
}
浏览器支持IE11+