我在绝对定位的div中的onmouseout函数遇到了麻烦。当鼠标击中div中的子元素时,mouseout事件发生,但我不希望它发生,直到鼠标离开父元素,绝对div。

我如何防止mouseout事件从发射时,它击中一个子元素没有jquery。

我知道这与事件冒泡有关,但我没有找到如何解决这个问题的方法。

我在这里找到了一个类似的帖子:如何禁用由子元素触发的鼠标退出事件?

但是,该解决方案使用jQuery。


当前回答

如果你添加(或拥有)一个CSS类或id到父元素,那么你可以这样做:

<div id="parent">
  <div>
  </div>
</div>

JavaScript:
document.getElementById("parent").onmouseout = function(e) {
  e = e ? e : window.event //For IE
  if(e.target.id == "parent") {
    //Do your stuff
  }
}

所以只有当事件在父div上时,才会执行东西。

其他回答

如果你正在使用jQuery,你还可以使用“mouseleave”函数,它可以为你处理所有这些问题。

$('#thetargetdiv').mouseenter(do_something);
$('#thetargetdiv').mouseleave(do_something_else);

Do_something将在鼠标进入targetdiv或其任何子div时触发,do_something_else仅在鼠标离开targetdiv及其任何子div时触发。

我用这个让它像魔法一样起作用:

function HideLayer(theEvent){
 var MyDiv=document.getElementById('MyDiv');
 if(MyDiv==(!theEvent?window.event:theEvent.target)){
  MyDiv.style.display='none';
 }
}

MyDiv标签是这样的:

<div id="MyDiv" onmouseout="JavaScript: HideLayer(event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

通过这种方式,当onmouseout转到子节点、孙子节点等时……的风格。Display ='none'不执行;但是当onmouseout退出MyDiv时,它会运行。

所以不需要停止传播,使用计时器等等……

谢谢例子,我可以从他们做这个代码。

希望这能帮助到一些人。

也可以这样改进:

function HideLayer(theLayer,theEvent){
 if(theLayer==(!theEvent?window.event:theEvent.target)){
  theLayer.style.display='none';
 }
}

然后DIVs标签是这样的:

<div onmouseout="JavaScript: HideLayer(this,event);">
 <!-- Here whatever divs, inputs, links, images, anything you want... -->
<div>

所以更一般,不只是一个div,不需要添加id="…"在每一层。

如果出于某种原因你不想使用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/

使用onmouseleave。

或者,在jQuery中使用mouseleave()

这正是你要找的东西。例子:

<div class="outer" onmouseleave="yourFunction()">
    <div class="inner">
    </div>
</div>

或者,在jQuery中:

$(".outer").mouseleave(function(){
    //your code here
});

这里有一个例子。

在Angular 5、6和7上

<div (mouseout)="onMouseOut($event)"
     (mouseenter)="onMouseEnter($event)"></div>

然后在

import {Component,Renderer2} from '@angular/core';
...
@Component({
 selector: 'app-test',
 templateUrl: './test.component.html',
 styleUrls: ['./test.component.scss']
})
export class TestComponent implements OnInit, OnDestroy {
...
 public targetElement: HTMLElement;

 constructor(private _renderer: Renderer2) {
 }

 ngOnInit(): void {
 }

 ngOnDestroy(): void {
  //Maybe reset the targetElement
 }

 public onMouseEnter(event): void {
  this.targetElement = event.target || event.srcElement;
  console.log('Mouse Enter', this.targetElement);
 }

 public onMouseOut(event): void {
  const elementRelated = event.toElement || event.relatedTarget;
  if (this.targetElement.contains(elementRelated)) {
    return;
  }
  console.log('Mouse Out');
 }
}