这是从哪里来的
当我第一次学习 jQuery 时,我通常会附加这样的事件:
$('.my-widget a').click(function() {
$(this).toggleClass('active');
});
在了解了更多关于选择器速度和事件委托(delegate)的知识后,我在几个地方读到“jQuery 事件委托(delegate)将使您的代码更快”。于是我开始写这样的代码:
$('.my-widget').on('click','a',function() {
$(this).toggleClass('active');
});
这也是复制已弃用的 .live() 事件行为的推荐方法。这对我很重要,因为我的很多网站一直在动态添加/删除小部件。上面的行为并不完全像 .live() ,因为只有添加到现有容器 '.my-widget' 的元素才会获得行为。如果我在该代码运行后动态添加另一个 html 块,这些元素将不会将事件绑定(bind)到它们。像这样:
setTimeout(function() {
$('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);
我想要达到的目标:
我现在附上所有这样的事件:
$(document).on('click.my-widget-namespace', '.my-widget a', function() {
$(this).toggleClass('active');
});
这似乎满足了我的所有目标。 (是的,由于某种原因,它在 IE 中变慢了,不知道为什么?)
它很快,因为只有一个事件与单个元素相关联,并且辅助选择器仅在事件发生时进行评估(如果这里有错误,请纠正我)。命名空间很棒,因为它可以更轻松地切换事件监听器。
我的解决方案/问题
所以我开始认为 jQuery 事件应该总是绑定(bind)到 $(document)。
你有什么理由不想这样做吗?
这可以被视为最佳实践吗?如果不是,为什么?
如果您已阅读全文,谢谢。我感谢任何/所有反馈/见解。
假设:
.on()
的 jQuery//至少版本 1.7 读物/例子:
最佳答案
不 - 您不应该将所有委托(delegate)的事件处理程序绑定(bind)到 document
对象。这可能是您可以创建的性能最差的场景。
首先,事件委托(delegate)并不总是能让你的代码更快。在某些情况下,这是有利的,而在某些情况下则不然。当您真正需要事件委托(delegate)并从中受益时,您应该使用事件委托(delegate)。否则,您应该将事件处理程序直接绑定(bind)到发生事件的对象,因为这通常会更有效。
其次,您不应该在文档级别绑定(bind)所有委托(delegate)事件。这就是为什么.live()
已弃用,因为当您以这种方式绑定(bind)大量事件时,这非常低效。对于委托(delegate)事件处理,将它们绑定(bind)到最近的非动态父级会更有效率。
第三,并非所有事件都有效或所有问题都可以通过委托(delegate)解决。例如,如果您想拦截输入控件上的键事件并阻止将无效键输入到输入控件中,则不能使用委托(delegate)事件处理来做到这一点,因为当事件冒泡到委托(delegate)处理程序时,它已经已由输入控件处理,现在影响该行为为时已晚。
以下是需要或有利事件委托(delegate)的时候:
要进一步理解这一点,需要了解 jQuery 委托(delegate)的事件处理程序是如何工作的。当你调用这样的东西时:
$("#myParent").on('click', 'button.actionButton', myFn);
它在
#myParent
上安装了一个通用的 jQuery 事件处理程序。对象。当单击事件冒泡到此委托(delegate)事件处理程序时,jQuery 必须检查附加到此对象的委托(delegate)事件处理程序列表,并查看事件的原始元素是否与委托(delegate)事件处理程序中的任何选择器匹配。因为选择器可能相当复杂,这意味着 jQuery 必须解析每个选择器,然后将其与原始事件目标的特征进行比较,以查看它是否与每个选择器匹配。这不是一个便宜的操作。如果只有一个选择器也没什么大不了的,但是如果您将所有选择器放在文档对象上并且有数百个选择器要与每个冒泡事件进行比较,这可能会严重影响事件处理性能。
出于这个原因,您希望设置委托(delegate)的事件处理程序,以便委托(delegate)的事件处理程序尽可能接近目标对象。这意味着更少的事件会通过每个委托(delegate)的事件处理程序冒泡,从而提高性能。将所有委托(delegate)事件放在文档对象上可能是最糟糕的性能,因为所有冒泡事件都必须经过所有委托(delegate)事件处理程序,并针对所有可能的委托(delegate)事件选择器进行评估。这就是为什么
.live()
已弃用,因为这就是 .live()
确实如此,但事实证明它非常低效。因此,要实现优化的性能:
关于javascript - 所有 jquery 事件都应该绑定(bind)到 $(document) 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12824549/