javascript - 向页面添加复杂元素时事件委托(delegate)与直接绑定(bind)

标签 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">
        <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>

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

介绍这些功能
$("#root").on("click", "li > header", function() {
  $(this).parent().toggleClass("collapsed");
});

li.collapsed section {
  display: none;
}

(附带问题:这是使用详细信息/摘要 HTML5 标签的合适位置吗?这些是否会进入最终规范似乎有点不确定,而且我想要一个滑动过渡,所以看起来像无论如何,我需要 JS。但我把这个问题抛给大众。大家好。)

如果根列表是保证在页面加载时存在的唯一(相关)元素,为了使 .on() 有效工作,我必须将所有事件绑定(bind)到该元素并拼出每个事件的精确选择器,据我了解。因此,例如,要将单独的功能绑定(bind)到彼此相邻的两个按钮,我必须每次都完整拼出选择器,à la

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

这准确吗?既然如此,放弃 .on() 并在新项目添加到页面时绑定(bind)我的事件是否更有意义?如果这对响应有影响的话,项目总数最多可能有几十个。

最佳答案

使用$(<root-element>).on(<event>, <selector>)绑定(bind)事件时您将产生更少的CPU开销因为您将绑定(bind)到单个“根”元素,而不是潜在的更多单个后代元素(每次绑定(bind)都需要时间...)。

话虽这么说,当实际事件发生时,您将产生更多的 CPU 开销,因为它们必须将 DOM 冒泡到“根”元素。

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

因此,由您来决定哪一点对性能更重要。添加新元素时是否有可用的 CPU?如果是这样,那么直接绑定(bind)到新元素将是整体性能的最佳选择,但是如果添加元素是 CPU 密集型操作,您可能希望委托(delegate)事件绑定(bind)并让事件触发从所有冒泡中创建一些额外的 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>) 的快捷方式.

更新

下面的性能测试表明,委托(delegate)事件绑定(bind)比单独绑定(bind)到每个元素更快:http://jsperf.com/bind-vs-click/29 . 遗憾的是,此性能测试已被删除。

更新

下面的性能测试显示,当您直接绑定(bind)到元素而不是委托(delegate)绑定(bind)时,事件触发速度更快:http://jsperf.com/jquery-delegate-vs-bind-triggering (请注意,这不是一个完美的性能测试,因为测试中包含了绑定(bind)方法,但由于 delegate 在绑定(bind)时运行得更快,这仅意味着 bind 在讨论触发时相对更快)

关于javascript - 向页面添加复杂元素时事件委托(delegate)与直接绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8827430/

相关文章:

Javascript 禁用 onclick 事件直到它的事件完成

javascript - 将事件附加到 DOM 上的所有内容的最明智的方法是什么?

javascript - 单击另一个 div 打开列表下拉列表

javascript - jQuery post 使用 ajax 来自可变数量的输入框

使用 elastislide 的 jQuery 动画问题

javascript - 检测特定图像何时完成加载

javascript - 影响当前外部元素中的另一个元素

javascript - 如何在一个打开时删除其他选项卡

javascript - YepNope - 等待依赖项加载

javascript - 集中捕获 JQuery 中的错误