如果元素插入 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>
我制作了一个简单的弹出窗口管理器,它使用 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>