鼠标悬停和mouseout事件的奇怪行为

时间:2016-11-28 10:59:45

标签: javascript html css javascript-events hover

我需要在将鼠标悬停在元素(触发器)上时显示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作为事件时也会发生这种情况。

为什么会这样?

4 个答案:

答案 0 :(得分:1)

正如Salasar已经说过的那样,这个问题的发生是因为第二个div,即悬停第一个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;
}

答案 1 :(得分:1)

除了之前的答案:你还可以将“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-element目前涵盖整个屏幕,您必须将其设置为“100px”而不是“100%”以获得更好的体验:

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

假设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;
}