3

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

我创建了一个简短的例子来说明这个问题。你可以在这里测试它:http: //threeds.me/0xC0DE/

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

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

但这不仅仅是事件。如果我将整个容器封装在一个标签中,则浏览器不会始终考虑单击该元素。所以就像改变子元素的可见性会使父母(相当)一段时间失明,我觉得这很奇怪。

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

这里是供您立即参考的来源

<!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>
4

2 回答 2

1

这真的很奇怪!但是,我做了一些测试并稍微修改了您的代码,现在我认为它与冒泡无关(您可以在我的测试中看到点击带有visibility: hidden气泡的元素就好了)。

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

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

因此,即使我没有得到解决方案,我也想了解问题所在。

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

最后但并非最不重要的一点是,关于您的代码的一些附注:

  1. setTimeout不推荐您调用的方式(传递字符串),因为它会强制在eval内部使用,eval应尽可能避免。无需将字符串与函数调用代码一起传递,只需传递函数本身:

    setTimeout(update, 100);
    
  2. 如今,使用addEventListener(或attachEvent 对于 IE)将事件绑定到元素被认为是一种最佳实践,而不是使用像onclick="...". 这有几个优点,比如帮助分离行为、结构和布局,并使事件对象自动可供事件处理程序使用(作为处理程序函数的第一个参数)。

于 2012-05-06T01:53:31.710 回答
0

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

您也可以在“容器”和“dfront”上创建透明层并将事件绑定到它。或者,在窗口对象上创建 onmouseclick 事件,这将通过检查它们的坐标来确定鼠标位置是否超过“dfront”,如果为 true,则将触发事件处理程序。

于 2012-05-05T21:21:23.693 回答