2017-11-11 34 views
1

我在index.html近六成过滤器按钮,每个都连有$().click()事件处理程序。jQuery的:如何确保事件处理程序连接到所有相关的元素在DOM

$(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()但这并没有影响。也可能是我所识别的问题(事件处理程序附加到元素太慢)是错误的,但我当然会很感激任何反馈。

+0

当然,如果你动态地添加它们,而不是在HTML中定义它们,那就不一样了。具体来说,它[会是这个](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements)。 –

+0

@ T.J.Crowder感谢您的反馈。如果通过“动态添加它们”表示这些元素本身,则HTML滤镜按钮都不是静态的。你是说'ready'回调通常可以确保所有的事件处理程序都会附加到它们的元素上吗? – orlando21

+0

所有'ready'保证的是,当DOM被完全解析时,你给它的回调将被调用。我想我知道你的情况发生了什么;看到我更新的答案。 :-) –

回答

2

我可以看到所描述的行为的唯一解释是,HTML是如此之大,它需要一段时间的浏览器来完成解析,并创建DOM。虽然这样做,它会部分渲染页面。通过使用ready,你告诉jQuery你不希望你的回调中的代码被调用,直到该过程完成。这给用户留下了一个(小)机会窗口,用户可以看到一个按钮并在点击处理程序被附加之前单击它(因为DOM解析仍在进行,所以ready回调尚未触发)。这符合描述的症状,特别是第一次点击不起作用(ready还没有开启),但后来的一次(同时触发了ready)。

如果这是发生了什么,你可以使用事件代表团等待ready回调避免:

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

挂接上document一个单击处理程序,将只被解雇如果点击通过了.filter_button_class元素。如果确实如此,那么您的处理程序名为,好像您已将该事件挂钩在该元素上。

这涉及到违反脚本规则之一,即在关闭</body>标记之前将它们放在HTML末尾。相反,特别是因为我们正在处理所造成的HTML的大小和DOM构建时间的问题,我们会打破这种规则,并把script标签有问题的内容上面:

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

再次,正常我们不会这样做,因为它使得DOM解析器等待脚本被提取,但在这种情况下,作为对已知问题的响应,没有问题。 (只要确保启用缓存和工作。)

你可以看到this fiddle通过(使用ready)比较this fiddle效果(使用委派的前期处理,然后还可以通过添加ready直接处理)。首先,如果你很快,你可以点击一个按钮,让它不显示任何东西。第二,如果你很快,你可以点击一个按钮,只获得“委托:”消息,但稍后如果你点击你会得到一个“直接:”消息,然后是“委托:”一个。

+0

这个downvoter喜欢分享一些关于**如何**的反馈,这是没有用的吗? –

+0

我认为你的建议是现货,因为我没有看到相反的证据。我仍在研究您的解决方案,但想要询问您的缓存意味着什么。你的意思是简单地把JavaScript放在单独的文件中 - 加载一次,然后他们仍然在记忆中,或者你有其他的东西吗?谢谢! – orlando21

+0

@ orlando21:我的意思是确保(例如)你从一个设置远期缓存头的源码加载jQuery,以便浏览器可以将它保存在缓存中。 (和你自己的脚本一样,如果它在一个单独的文件中)。 –

相关问题