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

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

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

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

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


当前回答

function onMouseOut(event) {
        //this is the original element the event handler was assigned to
        var e = event.toElement || event.relatedTarget;
        if (e.parentNode == this || e == this) {
           return;
        }
    alert('MouseOut');
    // handle mouse event here!
}



document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

我做了一个快速的JsFiddle演示,所有的CSS和HTML需要,检查它…

编辑固定链接跨浏览器支持http://jsfiddle.net/RH3tA/9/

注意,这只检查直接的父元素,如果父div有嵌套的子元素,那么你必须以某种方式遍历元素的父元素,寻找“原始元素”

编辑嵌套子的示例

编辑修复希望跨浏览器

function makeMouseOutFn(elem){
    var list = traverseChildren(elem);
    return function onMouseOut(event) {
        var e = event.toElement || event.relatedTarget;
        if (!!~list.indexOf(e)) {
            return;
        }
        alert('MouseOut');
        // handle mouse event here!
    };
}

//using closure to cache all child elements
var parent = document.getElementById("parent");
parent.addEventListener('mouseout',makeMouseOutFn(parent),true);

//quick and dirty DFS children traversal, 
function traverseChildren(elem){
    var children = [];
    var q = [];
    q.push(elem);
    while (q.length > 0) {
      var elem = q.pop();
      children.push(elem);
      pushAll(elem.children);
    }
    function pushAll(elemArray){
      for(var i=0; i < elemArray.length; i++) {
        q.push(elemArray[i]);
      }
    }
    return children;
}

和一个新的JSFiddle, EDIT更新链接

其他回答

简单地,我们可以检查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;
        }

    }

});
var elem = $('#some-id');
elem.mouseover(function () {
   // Some code here
}).mouseout(function (event) {
   var e = event.toElement || event.relatedTarget;
   if (elem.has(e).length > 0) return;

   // Some code here
});

下面是一个基于下面内容的更优雅的解决方案。 它解释了从一个以上层次的孩子中冒出来的事件。 它还考虑了跨浏览器的问题。

function onMouseOut(this, event) {
//this is the original element the event handler was assigned to
   var e = event.toElement || event.relatedTarget;

//check for all children levels (checking from bottom up)
while(e && e.parentNode && e.parentNode != window) {
    if (e.parentNode == this||  e == this) {
        if(e.preventDefault) e.preventDefault();
        return false;
    }
    e = e.parentNode;
}

//Do something u need here
}

document.getElementById('parent').addEventListener('mouseout',onMouseOut,true);

在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');
 }
}

我检查原始元素的偏移量以获得元素边界的页面坐标,然后确保只有当鼠标退出超出这些边界时才触发鼠标退出操作。很脏,但很管用。

$(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
}
}