【问题标题】:jQuery: is delegating always better than direct functions bindingjQuery:委托总是比直接函数绑定更好
【发布时间】:2015-08-27 01:06:02
【问题描述】:

使用$(document).on('click', selector, fn) 总是比使用$(selector).click(fn) 更好,因为第一个选择:

1) 可以处理动态创建的元素

2) 在页面加载过程中更快.. 对吗? (因为 JS 不必花时间查询和绑定函数到每个选择器)

忘记直接绑定并始终使用委托是否安全?

【问题讨论】:

  • 不是真的...过度使用会导致性能问题
  • 我没有进行足够的研究,但我认为两者是等价的。我相信,浏览器必须查询文档才能在这两种情况下找到元素。

标签: javascript jquery delegates click


【解决方案1】:

.on()

优势

委托事件具有可以处理来自 以后添加到文档中的后代元素。经过 选择一个保证在该时间存在的元素 附加了委托事件处理程序,您可以使用委托事件 避免频繁附加和删除事件处理程序的需要。在加载任何其他 HTML 之前,文档元素在文档头部是可用的,因此在此处附加事件是安全的,而无需等待文档准备好。

除了能够处理尚未创建的后代元素上的事件外,委托事件的另一个优点是当必须监视许多元素时,它们的开销可能会大大降低。

性能

在文档顶部附近附加许多委托事件处理程序 树会降低性能。每次事件发生时,jQuery 必须 将该类型的所有附加事件的所有选择器与每个 从事件目标到顶部的路径中的元素 文档。为获得最佳性能,请在文档中附加委托事件 位置尽可能靠近目标元素。避免过度 将 document 或 document.body 用于大型委托事件 文件。

.click()

这个方法是.on("click", handler)的快捷方式

【讨论】:

    【解决方案2】:

    通过我的研究,我得出一个结论,一个好的委托方法比直接绑定更好。让我们从乞讨开始。我们知道 dom 事件会从目标元素冒泡到它的父元素、祖父元素,直到 document。尽管 IE 和其他浏览器之间存在一些差异,但Jquery event 创建了一致的跨浏览器行为。因此,这两种方法的明显区别在于:

    直接绑定事件将在目标(或其后代)上发生并冒泡到document,而委托只是冒泡到最外面的绑定目标。考虑这个例子:

    $("#myBtn").click(function(){
        console.log("button was clicked");
    });
    
    document.onclick = function(){
        console.log("document is clicked");
    }
    <div id="testDiv" style="background:darkgrey">
        <button type="button" id="testBtn">click me</button>
    </div>

    当点击按钮时,document.onclick 将被触发。 但是,如果替换为委托方法,例如:

    $("#myDiv").on("click", "#myBtn", function(){
        console.log("myBtn was clicked");
    });

    document.onclick 不会被触发。同时注意点击最外面的myDiv不会触发事件。

    关键点来了。以良好的方式使用委托方法将极大地提高性能。参见这个例子(从professional javascript for web developer):

    <ul id="myLinks">
      <li id="goSomewhere"> Go somewhere </li>
      <li id="doSomething"> Do something </li> 
      <li id="sayHi"> Say hi </li>
    </ul>

    传统的直接绑定方式是:

    $("#goSomewhere").click(function(){
      window.location.href = "http://sample.com";  
    });
    
    $("#doSomething").click(function(){
      window.title = "I change the title";  
    });
    
    $("#sayHi").click(function(){
      alert("hi");  
    });

    如果点击事件多,绑定操作的次数会消耗大量内存,页面初始时间也会很长。我们可以通过委托减去一个绑定操作:

    $("#myLink").on("click", function(event){
        switch(event.target.id){
          case: "goSomewhere":
             window.location.href = "http://sample.com";
             break;
          case: "doSomething":
            window.title = "title was changed";
            break;
          case: "sayHi":
             alert("hi");
            break;
        }
    });

    这会减少大量内存的使用。为了更实用,如果有很多情况,您可能需要使用object 替换switch-case 模块以提高性能,例如:

    var eventHandler = {
      goSomewhere: function(){ window.location = "http://sample.com"; },
      doSomething: function(){ window.title = "title changed"; },
      sayHi: function(){alert("hi"); }
    }
    $("#myLink").on("click", function(event){
      if(eventHandler[event.target.id]) eventHandler[event.target.id]();
    });

    因为 javascript 的对象实际上是一个哈希表。

    然后,有一个想法:只需将单个事件附加到document 即可处理所有事件。对于mousedown、click、keydown等事件很实用,不适用于mouseout、mousein。优点很明显:我们只是绑定一个导致更少内存的事件,轻松删除事件处理程序,无需等待文档就绪事件,因为 document 已经可见,因为它的子 script 被读取。在联系中,如果你只是将每一个事件都绑定到document,那么优势就没有了。

    另外,如果使用直接绑定还有一个陷阱,例子来自jquery:考虑一个有1000行的表:

    $( "#dataTable tbody tr" ).on( "click", function() {
      console.log( $( this ).text() );
    });

    这会将处理程序附加到 1000 tr!但以下只是tbody 的单个附件:

    $( "#dataTable tbody" ).on( "click", "tr", function() {
      console.log( $( this ).text() );
    });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 2013-08-01
      • 2018-05-10
      • 1970-01-01
      • 1970-01-01
      • 2018-04-04
      相关资源
      最近更新 更多