Javascript委派最佳实践

时间:2013-12-20 15:30:46

标签: javascript jquery delegation

我正在开发/已经开发了一些系统,我在编程中遇到了一个问题,我似乎将所有我的JQuery函数委托给文档,如下所示:

$(document).on('click', '.modal-editor', function () {
    //code
});

$(document).on('click', '.another-class', function () {
    //code
});

$(document).on('click', '#another-id', function () {
    //code
});

这有什么问题吗?

更新

好的,基本上没有任何问题,直到:

  1. 应用程序达到了一种规模,其中委托需要更加本地化以防止减慢UI。 “发生的每个事件都需要针对e.target和文档之间的每个元素运行每个选择器”

  2. 如果使用嵌套函数,这样的委托会增加传播等意外行为的可能性。

  3. 回到我的问题(最佳实践),最佳做法是将事件委托给最接近的静态元素,以试图避免上述情况。

4 个答案:

答案 0 :(得分:4)

  

“这有什么问题吗?”

是。发生的每个事件都需要针对e.targetdocument之间的每个元素运行每个选择器。这是不必要的昂贵。

基本上就像这个简化的伪代码:

// start on the e.target
var node = e.target;

// For the target and all its ancestors until the bound element...
while (node && node !== this) {

    // ...test the current node against every click selector it was given
    for (var i = 0; i < click_selectors.length; i++) {

        // If a selector matches...
        if ($(node).is(selector)) {
            // ...run the handler for that selector
        }
    }
    node = node.parentNode;
}

此外,如果您加载的代码或其他代码在e.targetdocument之间绑定了处理程序,并且调用了e.stopPropagation(),则该事件将永远不会到达{{1} ,所以你的不会开火。

让你的代表团尽可能接近预期的要素会好得多。并且主要用于动态加载的元素,因为它增加了额外的开销,特别是在事件快速激发的情况下。

答案 1 :(得分:3)

是。实际上并不是真的,但是委托document(DOM的根)中的所有事件确实意味着所有点击事件,包括你所做的那些事件不感兴趣的将至少部分处理:

$(document).on('click', '$another-id', function(){});
在这方面,

是一个特别糟糕的主意:你在单个元素之后,但是如果我点击身体的任何地方,jQ会做类似的事情:

if (event.target.id == 'another-id')
{
    return callback.call(event.target, $(event));//where callback is the anonymous function you passed to on
}
return event;

所以所有点击事件都会导致函数调用。这可能会降低用户界面的速度 绝不应该停止委托事件,而是明智地绑定侦听器。例如,如果要使用的所有DOM元素都包含在#container div中,那么将侦听器绑定在那里。如果要处理导航事件,请将侦听器绑定到包含所有导航元素的节点 除此之外,如果您取消某个事件但未能 stopPropagation ,则该事件仍将最终调用可能排队的所有其他侦听器。 Returnign false也会造成麻烦,因为在jQ中,return false被翻译为e.preventDefault(); e.stopPropagation()。因此在处理嵌套元素时要小心,如果要处理页面中链接的点击,还要处理<a class='navigation'>等元素,可能会调用两个处理程序,具体取决于选择器使用:

$(document).on('click', 'a', function(){});//is called for all links
$(document).on('click', 'a.navigation', function(){});//is called for navigation

首先会调用哪个?在特定情况下,您想要使用哪个?这里有错误的余地,不应该出现在那里:

$('#navContainer').on('click', 'a.navigation', function(){});//is called for all links

至少使事情更安全,更清晰,更轻松。

如果您想使用ID选择器委派一个事件,并且该元素已存在于DOM中,不委托

$('#another-id').on('click', function(){});

更短,无论如何甚至可能更快

答案 2 :(得分:1)

您的代码没有任何问题,

$(document)不一定要永远放在事件委托中,选择器是指动态添加元素的最接近的父元素:

语法:

$(closest parent selector).on('event','target selector', function(){
});

您也可以使用document.body

$(document.body).on('event','target selecor',function(){
});

旁注:对于现有的 DOM 元素,您可以使用普通点击事件。

$('selector').click(function(){
});

$('selector').on('click',function(){
});

有关更多信息,请参阅.on() API文档。

答案 3 :(得分:1)

如果您希望将特定事件应用于多个元素,而不是每个元素都有自己的事件处理程序,那么委派就很棒。在上面的例子中,这可能是前两种方法。

如果只有一个元素符合理论上的标准,它可能会有一个性能含义,具体取决于文档的大小,因为必须针对处理程序过滤器测试每个事件以查看它是否匹配

此外,如果将每个方法添加为委托,并且您经常加载和上传页面的各个部分,那么这些事件将比它们所属的页面上的元素挂起的时间更长。

您可以将处理程序委派给文档元素以外的其他内容,例如周围的div或其他内容,而不是在这种情况下。或者使用事件命名空间来确保不会多次添加事件。