事件委托vs直接绑定时添加复杂的元素到页面

我有这样的标记(类只是为了解释):

<ol id="root" class="sortable"> <li> <header class="show-after-collapse">Top-Line Info</header> <section class="hide-after-collapse"> <ol class="sortable-connected"> <li> <header class="show-after-collapse">Top-Line Info</header> <section class="hide-after-collapse"> <div>Content A</div> </section> </li> </ol> </section> </li> <li> <header/> <section class="hide-after-collapse"> <ol class="sortable-connected"> <li> <header/> <section class="hide-after-collapse"> <div>Content B</div> </section> </li> </ol> </section> </li> </ol> 

也就是说,嵌套的可sorting列表。 但是,可sorting的插件就足够了,因为每个li(以下称为“item”)都保持其级别,尽pipe内部列表已连接。 这些项目在展开状态下有一个始终可见的标题和一个可见的部分,通过单击标题进行切换。 用户可以随意添加和删除任何级别的项目; 添加顶级项目将在其中包含一个空巢列表。 我的问题是关于新创build的项目的JS初始化:虽然他们将共享一些常见的function,我可以通过

 $("#root").on("click", "li > header", function() { $(this).parent().toggleClass("collapsed"); }); 

 li.collapsed section { display: none; } 

(旁边的问题:这是一个适当的地方使用的细节/总结HTML5标签?似乎有点如果这些甚至会使它成为最终规范,我想要一个滑动过渡,所以看起来像我会不pipe怎么样都需要JS,但是我把这个问题扔给群众,大家好。

如果根列表是在页面加载时唯一(相关)的元素,那么.on()可以有效地工作,所以我必须把所有的事件都绑定到这个元素上,明白它。 所以,例如,为了将两个button紧挨着的单独的function绑在一起,我必须每次都详细说明select器,

 $("#root").on("change", "li > section button.b1", function() { b1Function(); }).on("change", "li > section button.b2", function() { b2Function(); }); 

这是准确的吗? 既然如此,放弃.on()并绑定我的事件在新的项目被添加到页面是更有意义的? 如果这样做的话,那么这个项目的总数可能最多只有几十个。

因为您将绑定到单个“根”元素,而不是绑定更多的单个后代元素,所以在使用$(<root-element>).on(<event>, <selector>)绑定事件时,您将创build更less的CPU开销(每个绑定需要时间…)。

这就是说,当实际事件发生时,你将会承担更多的CPU开销,因为它们必须将DOM冒泡到“根”元素。

小结:委托在绑定事件处理程序时保存CPU; 绑定在事件触发时保存CPU(例如,用户点击某物)。

因此,决定哪一点对性能更重要取决于您。 当你添加新的元素时,你有可用的CPU吗? 如果是这样的话,直接绑定到新元素将是最好的总体性能,但是如果添加元素是一个CPU密集型操作,您可能需要委托事件绑定,并让事件触发创build一些额外的CPU开销从所有的冒泡。

注意:

 $(<root-element>).on(<event>, <selector>, <event-handler>) 

是相同的:

 $(<root-element>).delegate(<selector>, <event>, <event-handler>) 

然后:

 $(<selector>).on(<event>, <event-handler>) 

是相同的:

 $(<selector>).bind(<event>, <event-handler>) 

.on()在jQuery 1.7中是新的,如果你使用1.7+,那么.delegate(<selector>, <event>, <event-handler>)只是.on(<event>, <selector>, <event-handler>)

UPDATE

这是一个性能testing,表明委托事件绑定比分别绑定到每个元素更快: http : //jsperf.com/bind-vs-click/29 。 可悲的是,这个性能testing已经被删除。

UPDATE

这是一个性能testing,显示当直接绑定到元素而不是委托绑定时,事件触发速度更快:(请注意,这不是一个完美的性能因为绑定方法包含在testing中,但是由于delegate在绑定时运行速度更快,这意味着bind在谈到触发时甚至更快)

由于接受的答案有不准确的testing(顺便说一句: testing你的代码,衡量性能,不要盲目地遵循一些“规则” – 这不是一个优化是如何完成的!),只是错误我发布固定testing: https:// jsperf.com/jquery-delegate-vs-bind-triggering/49

这就certificate了这样一个简单的例子,代理或直接绑定没有区别

委托总是不好的事情是像鼠标移动和滚动的事件 – 每秒触发x次。 这是你会发现任何性能差异的地方。

如果你在单个事件上只有1ms的差异(不会发生,但这只是一个例子) – 就像点击一样 – 你不会注意到这一点。 如果您在1秒内发生100次的事件有1ms的差异 – 您将注意到CPU消耗。

只有有一千个元素不会对你的委派performance产生负面影响 – 事实上 – 这是他们应该使用的情况 – 当连接数千个事件处理程序时,避免占用CPU。

所以,如果你真的需要一个规则(不这样做) – 除了鼠标移动,滚动和其他事件,你可以期望连续发射,使用委托。

Interesting Posts