如果元素插入 DOM 中单击,则 onclick 不会触发

onclick not firing if element is reinserted into DOM mid-click

我制作了一个简单的弹出窗口管理器,它使用 dom 来决定哪个弹出窗口应该在前面,没有任何 z-index 规则:当我点击一个弹出窗口时,它会移动到第一个位置,所以它位于另一个弹出窗口之上。不幸的是:这个 dom 移动破坏了我弹出窗口中的 onclick 事件。

我对这个问题做了一个简单的说明:下面的代码应该输出三个点击事件:mousedown、mouseup 和 click,它适用于 Firefox,我认为它曾经适用于以前的版本 Chrome,但现在没有了。

<div>
  <div onmousedown="console.log('mousedown');this.parentElement.appendChild(this);" onmouseup="console.log('mouseup');" onclick="console.log('click');">Click</div>
</div>

你知道我该如何解决这个问题,并取回我的 onclick 事件吗?

如果将元素重新插入 DOM 会阻止其 click 事件触发,那么另一个选择是移动其兄弟元素。

这似乎有效(我建议以全页模式查看,因为控制台输出 中断事件,如果它覆盖了您刚刚单击的 div ):

function moveToFront(el) {
  var parent = el.parentElement;

  while (el.nextSibling) { 
    parent.insertBefore(el.nextSibling, el); 
  }
}

[].slice.call(document.getElementsByClassName('moveable')).forEach(function(el) {
  el.addEventListener('mousedown', function() {
    console.log('mousedown', this.id);
    moveToFront(this);
  });
  el.addEventListener('mouseup', function() {
    console.log('mouseup', this.id);
  });
  el.addEventListener('click', function() {
    console.log('click', this.id);
  });
});
.moveable {
  width: 100px;
  height: 100px;
  position: absolute;
}

#div1 {
  background-color: green;
  top: 10px;
  left: 10px;
}

#div2 {
  background-color: red;
  top: 40px;
  left: 40px;
}

#div3 {
  background-color: yellow;
  top: 20px;
  left: 70px;
}
<div>
  <div id="div1" class="moveable">Click</div>
  <div id="div2" class="moveable">Click</div>
  <div id="div3" class="moveable">Click</div>
</div>

并不是事件停止触发,只是您不再点击带有事件的 div。

注意 zIndexing,因为 zIndex 是相对于它的容器的。你不能有一个 zIndex 比它的父容器少的容器,否则你会把它移到它后面。 "dirty" 解决方案是让 zIndex 随着每次点击而增长:

<style type="text/css">
html, body{
    width: 100%;
    height: 100%;
}

.Movable{
    height: 100px;
    position: absolute;
    width: 100px;
}

.black{
    background-color: black;
}

.gray{
    background-color: gray;
}

.wheat{
    background-color: lightgray;
}

<div style="position: relative; z-index: 20;">
    <p id="log" style="height: 1em; overflow-y: scroll;"></p>
    <div onclick="log( 'clicked', this )" onmousedown="log( 'mousedown', this )" onmouseup="log( 'mouseup', this )" class="Movable black"></div>
    <div onclick="log( 'clicked', this )" onmousedown="log( 'mousedown', this )" onmouseup="log( 'mouseup', this )" style="left: 25px; top: 55px;" class="Movable gray"></div>
    <div onclick="log( 'clicked', this )" onmousedown="log( 'mousedown', this )" onmouseup="log( 'mouseup', this )" style="left: 55px; top: 75px;" class="Movable wheat"></div>
</div>
<script type="text/javascript">
    var index = 1;
    function log( msg, element )
    {
        element.style.zIndex = index++;
        document.getElementById( 'log' ).innerHTML += "Log: " + msg + " -> " + element.className + "</br>";
    }
</script>