如果元素在点击过程中重新插入DOM,则onclick事件不会触发

10
我制作了一个简单的弹出框管理器,使用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事件吗?

2个回答

4

如果重新插入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>


适用于Chrome,适用于IE11(OP的不适用),并且继续适用于Firefox。(我手头有的那些。)很好!奇怪,会让我担心其脆弱性。但很好! - T.J. Crowder
看起来比触发事件容易,而且效果非常好。+1 我会小心处理太多的兄弟姐妹/子元素 - 可能会影响性能(我认为这对 OP 不是问题)。 - Ricardo Ribeiro
1
@RicardoRibeiro 是的,我刚刚更改了它,所以它只移动目标元素后面的兄弟元素。看起来仍然有效。 - JLRishe

0

事件并没有停止触发,只是你不再点击带有该事件的 div 元素了。

在设置 zIndex 时要小心,因为 zIndex 是相对于其容器的。你不能让一个容器的 zIndex 小于它的父级元素,否则它会被移动到它的后面。"不太优雅" 的解决方案是让 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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接