jQuery:如何确保事件处理程序附加到DOM

时间:2017-11-11 14:20:13

标签: jquery

我在index.html中有大约60个过滤器按钮,每个按钮都附加了$().click()个事件处理程序。

$(document).ready(function() {
    $('.filter_button_class').click(function(e) {
        console.log("filter button clicked");
        e.preventDefault();
    });
});

在我的CSS文件中,:active选择器可确保点击过滤器按钮变为蓝色。

现在代码工作正常,大多数情况下。首次在浏览器中加载index.html时,事件处理程序似乎都正确附加,代码始终按预期工作。这是一个单页面应用程序,因此当用户点击后退按钮返回index.html并再次单击其中一个过滤器按钮时,它确实变为蓝色,但.click()处理程序内的代码有时不会不执行。

我怀疑这可能是因为重新加载index.html时,并非所有点击处理程序都会在用户点击过滤器按钮之前附加。但是当用户再次单击相同的过滤器按钮(总共两次)时,处理程序通常会执行。

问题有没有办法让click()内的代码等待执行,直到首先连接所有事件处理程序?

而不是.click()我还试过.on(),但这没有效果。也许我正在识别的问题(事件处理程序附加到元素太慢)是错误的,但我当然会欣赏任何反馈。

1 个答案:

答案 0 :(得分:2)

我能看到的描述行为的唯一解释是HTML非常大,浏览器需要一段时间才能完成解析并创建DOM。虽然它正在这样做,但它将部分呈现页面。通过使用ready,您告诉jQuery您不希望调用回调中的代码,直到该过程完成为止。这留下了一个(小)机会窗口让用户看到一个按钮并在附加点击处理程序之前单击它(因为DOM解析仍在发生,因此ready回调没有被触发然而)。这符合所描述的症状,特别是第一次点击不起作用(ready尚未解雇),但后续的点击(ready同时被解雇)。< / p>

如果 发生了什么,您可以通过使用事件委派和来等待ready回调:

$(document).on("click", ".filter_button_class", function() {
    // ...handle the click...
});

挂钩document上的点击处理程序,只有点击通过.filter_button_class元素才会被触发。如果是这样,你的处理程序被称为,就好像你已经在该元素上挂钩了事件。

这涉及破坏脚本的一个规则,即将它们放在HTML的末尾,就在结束</body>标记之前。相反,特别是因为我们正在处理由HTML大小和DOM构建时间引起的问题,我们违反了该规则并将script标记置于问题内容之上:

<script src="jquery.js"></script>
<script src="yourcode.js"></script>
<!-- problematic (large) content -->

同样,通常我们不会这样做,因为它使得DOM解析器等待获取脚本,但在这种情况下,作为对已知问题的响应,它很好。 (只需确保启用缓存并正常工作。)

您可以通过将this fiddle(使用ready)与this fiddle进行比较来查看效果(使用委托的前端处理程序,然后通过ready添加直接处理程序)。第一个,如果您快速,您可以单击一个按钮,让它不显示任何内容。对于第二个,如果您快速,您可以单击一个按钮,只获得&#34;委派:&#34;消息,但稍后如果你点击了,我会得到一个&#34;直接:&#34;消息,然后是&#34;委托:&#34;之一。