【问题标题】:Strange behavior of mouseover and mouseout eventsmouseover 和 mouseout 事件的奇怪行为
【发布时间】:2017-04-12 01:52:33
【问题描述】:

我需要在将鼠标悬停在元素(触发器)上时显示HTMLElement,并在离开相同元素时隐藏它。

工作示例

这里显示/隐藏的元素没有悬停在触发元素上。

var div = document.createElement("div");
div.className = "d";
document.body.appendChild(div);

var hov = document.createElement("div");
hov.className = "h";

var hover = false;

var overEvent = "mouseenter";
var overOut = "mouseleave";

div.addEventListener(overEvent, function(e) {
  if (hover) return;
  
  document.body.appendChild(hov);
  hover = true;
  
  console.log("OVER");
});
div.addEventListener(overOut, function(e) {
  if (!hover) return;
  
  document.body.removeChild(hov);
  hover = false;
  
  console.log("OUT");
});
.d {
  width: 100px;
  height: 100px;
  background-color: #ff9900;
  z-index: 0;
}

.h {
  width: 100px;
  height: 100px;
  top: 150px;
  bottom: 150px;
  background-color: #000000;
  opacity: 0.5;
  z-index: 1;
}

div {
  position: absolute;
}

不工作

在这里,触发器被覆盖,事情变得奇怪:

var div = document.createElement("div");
div.className = "d";
document.body.appendChild(div);

var hov = document.createElement("div");
hov.className = "h";

var hover = false;

var overEvent = "mouseenter";
var overOut = "mouseleave";

div.addEventListener(overEvent, function(e) {
  if (hover) return;
  
  document.body.appendChild(hov);
  hover = true;
  
  console.log("OVER");
});
div.addEventListener(overOut, function(e) {
  if (!hover) return;
  
  document.body.removeChild(hov);
  hover = false;
  
  console.log("OUT");
});
.d {
  width: 100px;
  height: 100px;
  background-color: #ff9900;
  z-index: 0;
}

.h {
  width: 100%;
  height: 100%;
  background-color: #000000;
  opacity: 0.5;
  z-index: 1;
}

div {
  position: absolute;
}

在这种情况下,我可以看到在触发元素上移动鼠标时重复调用侦听器,导致这种有趣的间歇性不良效果被多次放置和移除。

当使用 mouseovermouseout 作为事件时也会发生这种情况。

为什么会这样?

【问题讨论】:

  • 因为 mouseover 触发元素在 overlay box 后面,您需要使用 click 事件来打开覆盖或不要让覆盖覆盖它mouseover 触发元素。

标签: javascript html css hover dom-events


【解决方案1】:

正如 Salasar 已经说过的,这个问题的发生是因为第二个 div,即在悬停第一个时显示的那个,准确地显示了鼠标所在的位置,这会在第一个 div 上触发鼠标移出事件。你可以做些什么来解决这个问题,将你的第二个 div div.h 配置为“pointer-events: none”。 This will make it never to be a target of mouse events.

我已更新您的示例以显示此功能。

var div = document.createElement("div");
div.className = "d";
document.body.appendChild(div);

var hov = document.createElement("div");
hov.className = "h";

var hover = false;

var overEvent = "mouseenter";
var overOut = "mouseleave";

div.addEventListener(overEvent, function(e) {
  if (hover) return;
  
  document.body.appendChild(hov);
  hover = true;
  
  console.log("OVER");
});
div.addEventListener(overOut, function(e) {
  if (!hover) return;
  
  document.body.removeChild(hov);
  hover = false;
  
  console.log("OUT");
});
.d {
  width: 100px;
  height: 100px;
  background-color: #ff9900;
  z-index: 0;
}

.h {
  width: 100%;
  height: 100%;
  background-color: #000000;
  opacity: 0.5;
  z-index: 1;
  pointer-events: none;
}

div {
  position: absolute;
}

【讨论】:

    【解决方案2】:

    除了前面的答案:您还可以将“remove div”事件侦听器添加到“hov”元素而不是“div”元素。那将立即解决您的问题。这是整个代码以及一些小的提示/改进:

    var div = document.createElement("div");
    div.className = "d";
    document.body.appendChild(div);
    
    var hov = document.createElement("div");
    hov.className = "h";
    
    var hover = false;
    
    var overEvent = "mouseenter";
    var overOut = "mouseleave";
    
    div.addEventListener(overEvent, function(e) {
        // if (hover) return; <-- you don't need that
    
        document.body.appendChild(hov);
        hover = !hover; // <-- that's easier to maintain incase you're changing the initial value
    
        console.log("OVER");
    });
    hov.addEventListener(overOut, function(e) {
        // if (!hover) return; <-- you don't need that
    
        document.body.removeChild(hov);
        hover = !hover;
    
        console.log("OUT");
    });
    

    提示:您的 hov 元素当前覆盖整个屏幕,您必须将其设置为“100px”而不是“100%”以获得更好的体验:

    .h {
        width: 100px;
        height: 100px;
        background-color: #000000;
        opacity: 0.5;
        z-index: 1;
    }
    

    【讨论】:

      【解决方案3】:

      这是因为上层元素用处理程序覆盖了元素。因此,当上元素发生时,下一个鼠标运动会调用“mouseleave”的处理程序。

      【讨论】:

        【解决方案4】:

        假设 hov 在 DOM 顺序中遵循 div,您可以使用 CSS 控制其可见性。

        var div = document.createElement("div");
        div.className = "d";
        document.body.appendChild(div);
        
        var hov = document.createElement("div");
        hov.className = "h";
        document.body.appendChild(hov);
        .d {
          width: 100px;
          height: 100px;
          background-color: #ff9900;
          z-index: 1;
        }
        
        .h {
          width: 100%;
          height: 100%;
          background-color: #000000;
          opacity: 0.5;
          display: none;
          z-index: 0;
        }
        
        div {
          position: absolute;
        }
        
        .d:hover + .h {
          display: block;
        }

        【讨论】:

          猜你喜欢
          • 2011-04-13
          • 1970-01-01
          • 2020-09-25
          • 2013-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-07-29
          • 1970-01-01
          相关资源
          最近更新 更多