Javascript - mouseover/out 事件同时在所有兄弟元素上触发

Javascript - mouseover/out event fires on all sibling elements at the same time

我有四个 class 为 "box" 的兄弟元素。我使用带有 for 循环的 getElementsByClassName() 来迭代匹配的元素集,并使用 addEventListener() 方法将 mouseover 事件绑定到每个元素。

我遇到的问题 是当我在事件处理程序中使用 .style.display 并将鼠标悬停在任何匹配元素上时,所有前面的兄弟匹配元素更改它们的显示值。

如果我使用 .style.backgroundColor 等不同的样式方法,一切正常。我用 google 和 youtubed 搜索过,但找不到解决方案。我将不胜感激任何帮助,谢谢。

代码:

function hover(eClass) {
  var elem = document.getElementsByClassName(eClass);
  for (var i=0;i<elem.length;i++) {
    elem[i].addEventListener('mouseover', mouseOver);
    elem[i].addEventListener('mouseout', mouseOut);
  }
  function mouseOver() {    
    //this.style.backgroundColor = 'red';
    this.style.display = 'none';
  }
  function mouseOut() {
    //this.style.backgroundColor = 'grey';
  }  
}
hover('box');

Codepen example

我检查了你的代码。没关系。事实上,如果您尝试将鼠标悬停在最后一个(底部)方块上,它只会消失。当您将鼠标悬停在最上面的一个时,它会消失,下一个会成为最上面的一个,所以它也会消失,依此类推,直到所有的消失。这发生得太快了,所有的方块都立刻消失了……

这很有趣,过了一段时间才发现这只是一个实际问题。当您将鼠标悬停在第一个框上时,它会被移除,而下一个框会在其位置重新绘制。但是随后该事件在方框 2 上再次触发,因为 it 现在位于光标下方,因此它会继续。当然,这发生得太快了,看不到,但这就是正在发生的事情。如果您真的想从浏览器的绘制功能中删除该元素,则必须想办法停止在下一个元素上触发事件,或者设置 opacity: 0.

更新

这有点丑陋,但是删除事件侦听器并再次添加它们演示了可以如何工作。 http://codepen.io/dannyjolie/pen/mPmpqE

function mouseOver() {
  //this.style.backgroundColor = 'red';
  removeListeners('box');
  this.style.display = 'none';
  setTimeout(function(){
    addListeners('box');
  }, 100);
}

misher 打败了我,但是是的,这就是正在发生的事情。我把 1 - 4 放在 DIVs:

<div class="container">
    <div class="box grey">1</div>
    <div class="box grey">2</div>
    <div class="box grey">3</div>
    <div class="box grey">4</div>
</div>

并使用 console 捕捉元素的 innerHTML 并且它们消失了,这给了我:

1
2
3
4

毫不奇怪,一旦 display 设置为 none,元素就会向上移动,因为您悬停的元素不再有 CSS 发挥作用。您可以使用 visibility 来防止这种情况发生,但是 mouseout 事件不会在不可见元素上触发。

稍微调整一下,您可以使用 data 属性和 mousemove 事件来保持元素的位置;这只会触发一次,因此如果页面调整大小或移动 X 和 Y 值将关闭,也许 window.onresize 可以解决这个问题,但这里是:

function hover(eClass) {
    var elem = document.getElementsByClassName(eClass);
    for (var i = 0; i < elem.length; i++) {
        elem[i].addEventListener('mouseover', mouseOver);
    }
    document.addEventListener('mousemove', mouseMove);
    function mouseOver() {
        var minX = this.offsetLeft;
        var maxX = minX + this.offsetWidth;
        var minY = this.offsetTop;
        var maxY = minY + this.offsetHeight;
        this.setAttribute('data-minx', minX);
        this.setAttribute('data-maxx', maxX);
        this.setAttribute('data-miny', minY);
        this.setAttribute('data-maxy', maxY);
        this.style.visibility = 'hidden';
    }
    function mouseMove(e) {
        e = e || event;
        for(i = 0; i < elem.length; i++) {
            var div = elem[i];
            var minX = div.getAttribute('data-minx');
            var maxX = div.getAttribute('data-maxx');
            var minY = div.getAttribute('data-miny');
            var maxY = div.getAttribute('data-maxy');
            if(e.clientX >= minX && e.clientX <= maxX && e.clientY >= minY && e.clientY <= maxY) {
                // over the Div
            } else {
                div.style.visibility = 'visible';
            }
        }
    }
}

hover('box');