Event delegation vs direct binding when adding complex elements to a page
我有一些这样的标记(类只是为了说明):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <li> <header class="show-after-collapse">Top-Line Info</header> <section class="hide-after-collapse"> <li> <header class="show-after-collapse">Top-Line Info</header> <section class="hide-after-collapse"> Content A </section> </li> </section> </li> <li> <header/> <section class="hide-after-collapse"> <li> <header/> <section class="hide-after-collapse"> Content B </section> </li> </section> </li> |
即嵌套的可排序列表。可排序的插件就足够了,因为尽管内部列表已连接,但每个li(以下称" item")都保持其级别。这些项目具有始终可见的标题和在展开状态下可见的部分,可通过单击标题进行切换。用户可以随意从任一级别添加和删除项目。添加顶级商品将在其中包含一个空的嵌套列表。我的问题是关于新创建项目的JS初始化:尽管它们将共享一些通用功能,但我可以通过
进行介绍
1 2 3 | $("#root").on("click","li > header", function() { $(this).parent().toggleClass("collapsed"); }); |
和
1 2 3 | li.collapsed section { display: none; } |
(旁问:这是使用details / summary HTML5标签的合适地方吗?对于这些标签是否甚至可以将其纳入最终规范似乎有些不确定,我想进行一次滑动过渡,所以看起来无论如何,我都需要JS。但是我把这个问题扔给了大众。你好,大众。)
如果根列表是保证页面加载时存在的唯一(相关)元素,为了使.on()有效运行,我必须将所有事件绑定到该元素,并为每个元素拼出精确的选择器据我了解。因此,例如,要将单独的功能绑定到彼此相邻的两个按钮上,我每次都必须完整拼写选择器,
使用
也就是说,当实际事件发生时,您将招致更多的CPU开销,因为它们必须使DOM膨胀到" root "元素。
短篇小说:绑定事件处理程序时,委托可以节省CPU;当事件触发时(例如用户单击某物),bind可以节省CPU。
由您决定哪个点对性能更重要。添加新元素时,您是否有可用的CPU?如果是这样,则直接绑定到新元素将是整体性能最佳的选择,但是如果添加元素是占用大量CPU的操作,则您可能需要委派事件绑定,并让事件触发从所有冒泡事件中产生一些额外的CPU开销。
请注意:
1 | $(<root-element>).on(<event>, <selector>, <event-handler>) |
与:
相同
1 | $(<root-element>).delegate(<selector>, <event>, <event-handler>) |
那:
1 | $(<selector>).on(<event>, <event-handler>) |
与:
相同
1 | $(<selector>).bind(<event>, <event-handler>) |
更新
此处是一项性能测试,表明委派事件绑定比单独绑定每个元素要快:http://jsperf.com/bind-vs-click/29。 s>不幸的是,这性能测试已删除。
更新
此处是一项性能测试,显示当您直接绑定到元素而不是委派绑定时,事件触发会更快:http://jsperf.com/jquery-delegate-vs-bind-triggering(请注意,这不是\\' ta完美的性能测试,因为绑定方法包含在测试中,但是由于
由于接受的答案具有不正确的测试(顺便说一句:测试您的代码,衡量性能,不要只是盲目地遵循一些"规则",这不是优化的方法!),这是错误的,我已修复测试:
https://jsperf.com/jquery-delegate-vs-bind-triggering/49
证明在这样简单的示例中,委托或直接绑定之间没有区别
委派总是很糟糕的唯一情况是鼠标移动和滚动之类的事件-每秒触发x次。在这里,您会发现任何性能差异。
如果您在单个事件上(例如单击)甚至相差1毫秒(不会发生,但这只是一个例子),您将不会注意到这一点。如果您在一秒钟内发生100次事件的时间差为1毫秒-您会注意到CPU消耗。
仅拥有数千个元素不会对委派的性能产生负面影响-实际上-应该使用它们的情况-避免在附加数千个事件处理程序时占用CPU。
因此,如果您确实需要遵循规则(不要这样做),请对除鼠标移动,滚动和其他可能会持续触发的其他事件以外的所有事物使用委派。