更改元素的可见性时不会调用事件

时间:2012-05-05 20:57:07

标签: javascript events dom

我有一个页面需要定期切换div的可见性。问题是通常不会调用与其中一个父元素相关的点击事件。如果我停止可见性切换或者我放慢速度(例如300ms而不是100ms),则会正常触发点击事件。

我已经创建了一个简短的例子来说明这个问题。 您可以在此处进行测试:http://threeds.me/0xC0DE/

单击蓝色/红色方块理论上应该触发click事件。如果没有动画(此处为默认行为),单击蓝色方块将始终触发onclick事件。如果单击“播放/暂停”,红色方块的可见性将开始每100毫秒切换一次。播放动画时,每次单击正方形时都不会调用click事件。

我怀疑改变可见性会以某种方式弄乱DOM,因此DOM会在几毫秒内停止事件。我还尝试切换css visibility属性以最小化对页面的影响,但结果相同。

但这不仅仅是事件。如果我将整个容器封装在标记中,则浏览器不会始终单击该元素。因此,改变子元素的可见性会让父母在某个时间(相当)失明,我觉得这很奇怪。

这个问题与Firefox,Chrome和Opera一致(所有这些都在Mac上,无法测试即是)所以这意味着有些东西我没有得到。所以,即使我没有得到解决方案,我也想了解问题所在。

此处是您的直接参考资料来源

<!DOCTYPE html>
<html>
<head><title>Wiggle problem</title>
<style>
#dback {
    width: 200px;
    height: 200px;
    background-color: red;
}
#dfront {
    width: 200px;
    height: 200px;
    background-color: blue;
}
</style>

<script type="text/javascript">
var run = false;
function playpause() {
    if ( run ) {
        run = false;
    } else {
        run = true;
        update();
    }
}

function update() {
    if ( run==false ) {
        return;
    }

    var el = document.getElementById('dfront');
    if ( el.style.display != 'none' ) {
        el.style.display = 'none';
    }
    else {
        el.style.display = '';
    }

    setTimeout("update();", 100);
}
</script>

</head>

<body>
<a href="#" onclick="playpause();">play/pause</a>
<div id="container" onclick="d=new Date();t=d.getTime();document.getElementById('info').innerText='click '+t;">
    <div id="dback">
        <div id="dfront"></div>
    </div>
</div>
<span id="info"></span>
</body>
</html>

2 个答案:

答案 0 :(得分:1)

这真的很奇怪!但是,我做了一些testsfiddled with your code,现在我觉得它与冒泡无关(你可以在我的测试中看到点击visibility: hidden气泡的元素就好了)。

以下是认为可能会发生的事情:由于您的计时器间隔太短,因此没有足够的时间来注册实际点击 - 点击是mousedown事件,后跟mouseup事件,在同一元素上。在你的情况下会发生mouseup经常被另一个元素触发,而不是触发mousedown的那个元素,因此没有click事件。请参阅上面的第二个链接,我将间隔缩短为1秒,然后尝试单击蓝色方块,然后释放红色方块上的鼠标按钮(反之亦然)。什么都没发生。我可能完全错了,但看起来似乎有道理。

我知道这不是解决方案,但你说:

  

所以,即使我没有得到解决方案,我也想了解问题是什么。

我希望这可以帮助你找到一个!

最后但并非最不重要的是,您的代码有几个附注:

  1. 建议您调用setTimeout(传递字符串)的方式,因为它会在内部强制使用eval,并尽可能强制使用eval should be avoided 。而不是使用函数调用代码传递字符串,只需传递函数本身:

    setTimeout(update, 100);
    
  2. 今天最好的做法是使用addEventListener(或attachEvent用于IE)将事件绑定到元素,而不是使用像onclick="..."这样的内联事件。这有几个优点,例如帮助分离行为,结构和布局,以及使事件对象自动可用于事件处理程序(作为处理函数的第一个参数)。

答案 1 :(得分:0)

实际上,当“dfront”可见时,它会悬停在“容器”上,当您点击时,事件会转到“dfront”。但是对于“dfront”元素没有onclick事件。 “容器”的Onclick事件不会在子元素上传播 - 它是正常的,您可以使用jquery来解决它,它具有事件的“事件传播”选项。 或者只为“dfront”设置onclick事件。

您还可以在“container”和“dfront”上创建透明图层并将事件绑定到它。 或者,在窗口对象上创建onmouseclick事件,如果鼠标位置超过“dfront”,通过检查它们的坐标,如果为true,那么将触发事件处理程序。