Javascript 向页面添加复杂元素时事件委派与直接绑定

Javascript 向页面添加复杂元素时事件委派与直接绑定,javascript,jquery,jquery-events,event-delegation,Javascript,Jquery,Jquery Events,Event Delegation,我有一些标记,比如这些类只是为了解释: <ol id="root" class="sortable"> <li> <header class="show-after-collapse">Top-Line Info</header> <section class="hide-after-collapse"> <ol class="sortable-connected"> <

我有一些标记,比如这些类只是为了解释:

<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>

附带问题:这里是否适合使用详细信息/摘要HTML5标记?这似乎有点不确定这些是否会进入最终的规范,我想要一个滑动转换,所以我似乎无论如何都需要JS。但我把这个问题抛给了大众。大家好

如果根列表是保证在页面加载时存在的唯一相关元素,那么为了有效地工作,我必须将所有事件绑定到该元素,并按照我的理解为每个元素指定精确的选择器。例如,要将单独的函数绑定到相邻的两个按钮上,每次我都必须完整地拼写选择器,a la

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

准确吗?在这种情况下,在将新项目添加到页面时放弃.on并绑定我的事件是否更有意义?如果这会对响应造成影响,那么项目的总数最多可能会达到几十个。

使用$.on绑定事件时,将减少CPU开销,因为您将绑定到单个根元素,而不是每个绑定可能需要更多的单子代元素

也就是说,当实际事件发生时,您将产生更多的CPU开销,因为它们必须将DOM冒泡到根元素

简短的故事:当绑定事件处理程序时,委托节省了CPU;当事件触发时(例如,用户单击某物),bind可节省CPU

因此,由您决定哪一点对性能更重要。添加新元素时是否有可用的CPU?如果是这样的话,那么直接绑定到新元素对整体性能来说是最好的,但是如果添加元素是CPU密集型操作,那么您可能会希望委托事件绑定,并让事件触发从所有冒泡中产生一些额外的CPU开销

请注意:

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

$(<root-element>).delegate(<selector>, <event>, <event-handler>)
$(<selector>).bind(<event>, <event-handler>)
而且:

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

$(<root-element>).delegate(<selector>, <event>, <event-handler>)
$(<selector>).bind(<event>, <event-handler>)
.on在jQuery1.7中是新的,如果您使用的是1.7+那么.delegate只是.on的捷径

更新

下面是一个性能测试,它显示委托事件绑定比单独绑定到每个元素更快:。遗憾的是,这个性能测试已经取消

更新


下面是一个性能测试,它表明当您直接绑定到元素而不是委托绑定时,事件触发会更快:请注意,这不是一个完美的性能测试,因为绑定方法包含在测试中,但由于委托在绑定时运行得更快,这就意味着在谈到触发时绑定相对更快,因为公认的答案有不准确的测试。顺便说一句:测试代码,衡量性能,不要盲目地遵循一些规则-优化不是这样做的!这完全是错误的,我发布了修复测试:

这证明在这样一个简单的例子中,委托和直接绑定之间没有区别

只有鼠标移动和滚动这样的事件才会导致委派失败,这些事件每秒会触发x次。这就是您将注意到任何性能差异的地方

若你们有1毫秒的差异,那个么这种情况就不会发生,但这只是一个单一事件的例子——比如点击——你们不会注意到这一点。若你们在一秒钟内发生100次的事件上有1ms的差异,你们会注意到CPU消耗

仅仅拥有数千个元素不会对委派的性能产生负面影响-实际上-应该使用它们时就是这种情况-以避免在附加数千个事件处理程序时占用CPU


所以,如果你真的需要遵守规则,不要这样做-除了鼠标移动、滚动和其他可能持续触发的事件之外,在所有事情上都使用委派。

+1,我希望看到一个详细的回复,可能会概述性能方面的考虑。在我看来,如果您知道上限最多是几十个,那么这两种方法都可以。但我相信你知道,有时候这些东西会随着时间的推移而增长……总共会有几十种元素,还是会有几十种单一类型的元素?在您的示例button.b2中,是否会有这些代码中的一个或可能有几十个?@nnnnnn,这种情况几乎肯定是以低三位数为界的,但这里有很多热心的复制粘贴者,谁知道他们会借用代码做什么,所以重点是。@JamesMontagne,外部列表是集合,其中唯一的元数据是名称,但内部列表是这些集合中的资产,这些集合中有一大堆需要显示/处理的元数据。这是CMS的一部分。谢谢,这太棒了。我认为直接绑定在我的例子中更有意义,因为对现有项激发的事件比添加新项更频繁。另外,这会让我对sel更聪明
ectors。查看了性能测试。触发对每个绑定项的单击会产生误导,因为用户可能不会这样做。从初始负载的角度来看,委托的性能远远优于代理。@JECarterII我没有创建很多性能测试,但我认为这样做的目的是在单击链接时显示性能的%差异。点击更多的链接会得到更大的数据集,应该会得到更准确的统计平均值,对吗?还是我遗漏了什么?我还认为在两个测试中都使用.find很好,因为它不会因为只在一个测试中使用.find而不在另一个测试中使用而影响性能,这就是为什么我认为您的测试存在如此大的性能差距。@Jasper-如果您有一个基于实际使用的用例,那么测试完整用例的性能是好的。我从构建测试的方式推断出的用例对我来说似乎有点不真实。我想这取决于您是在寻找不同代码块的并排比较,还是试图找到最好的用户体验。对于用户来说,页面加载和控件绑定比单击事件更耗时,因此我只考虑这组条件。我希望我说得有道理-@jasper您的jsperf测试的结果是无效的,因为您在绑定事件之后没有清理它们。这里是一个版本的测试,我已经交换了测试的顺序,并将点击模拟从实际绑定中分离出来:我认为在大多数情况下,您应该更喜欢委托。