【问题标题】:What is the fastest way to dynamically generate a list in jQuery Mobile在 jQuery Mobile 中动态生成列表的最快方法是什么
【发布时间】:2013-07-12 22:08:59
【问题描述】:

我正在创建一个 jQuery 移动应用程序,其中 UI 事件会动态生成列表。因此,我使这些列表出现的速度越快,我的 UI 就会显示得越灵敏。我在下面概述了一些方法。我希望具有网络性能专业知识的人可以告诉我他们认为哪种方法最好,或者提出一种全新的方法。

方法#1“以编程方式生成

  • 列表元素对象数组中的选择器"
    $.each(array, function(index, value){
    var listElement = "$(<li></li>)";
    listElement.text(array.elementName);
    //Do some other stuff to listElement
    $("#displayedList").append(listElement);
    //append to Displayed List
    });
    

    方法#2“克隆”

  • 来自列表元素对象数组的 dom 对象的元素”
    $.each(array, function(index, value){
    var listElement = $("#listElementTemplate").clone();
    //Cloned list element from already loaded dom element
    listElement.text(array.elementName);
    //Do some other stuff to listElement
    $("#displayedList").append(listElement);
    //append to Displayed List
    });
    

    方法 #3“在 iframe 中显示已加载的列表”

    $("#displayedListWrapper").find("iframe").src("#loadedList");
    
  • 【问题讨论】:

    • 我相信第一种方法是最好的,因为您可以在将内容注入 DOM 之前轻松修改它们。您只需致电.listview('refresh') 以增强他们的标记。方法 #2 克隆,复制增强标记并使其有点难以修改,因为您需要更深入地了解增强标记才能进行更改。
    • 嗨@omar 我预计修改或css刷新在任何情况下都不会成为问题。我最关心的是速度。
    • fiddle.jshell.net/Palestinian/4qH6E 随时单击以获取创建 1000 个列表项的时间。

    标签: jquery performance list jquery-mobile dynamically-generated


    【解决方案1】:

    这是我为您的场景制作的 jsPerf:http://jsperf.com/dynamic-li

    设置

    这是我为此使用的示例 JSON:

    [
        "Sweet Child 'O Mine",
        "Summer of '69",
        "Smoke in the Water",
        "Enter Sandman",
        "I thought I've seen everything",
        "Never Hear Surf Music Again",
        "The Canyon",
        "Liberation Begins",
        "Touch of the Sun",
        "Lovely Day",
        "Ca Plane Pour Moi",
        "Liberation In A Dream",
        "If You Love Me (Really Love Me)",
        "Acid Darbari",
        "R.I.P.",
        "Festival",
        "If I Rise",
        "Liberation",
        "Nocturne No. 2 in E flat"
    ]
    

    并且使用的测试方法是:

       //Scenario #1 : Programmatically generate li elements
       function makeLiProgrammatically() {
           $.each(songs, function (i, song) {
               var listElement = $("<li></li>");
               listElement.text(song);
               $list.append(listElement);
           });
           $list.listview("refresh");
       }
       //Scenario #2 : Clone DOM <li> element
       function cloneDOMLi() {
           $.each(songs, function (i, song) {
               var listElement = $("#listElementTemplate").clone();
               //Cloned list element from already loaded dom element
               listElement.text(song);
               //Do some other stuff to listElement
               $list.append(listElement);
               //append to Displayed List
           });
    
           $list.listview("refresh");
       }
       //Extra scenario - replacing each loop with for loop in scenario #1
       function makeLiProgrammaticallyForLoop() {
           for (; i < songs.length; i++) {
               var listElement = $("<li></li>");
               listElement.text(songs[i]);
               $list.append(listElement);
           };
           $list.listview("refresh");
       }
    

    最后一个场景是我的补充,只是为了检查for在这个场景中是否优于each。结果是.. drumroll

    结果

    看起来像以编程方式添加&lt;li&gt;for 循环 是最快的!正如奥马尔所说,原因很简单。您正在内存中创建一个元素,因此它不会消耗那么多内存。然而,在您的场景 #2 中,您要去 DOM,搜索 li 元素(也重复),这会减慢速度。 - 参见编辑

    希望这可以解决问题!

    PS 不要介意 jsPerf 中搞砸的格式,我认为 jQM 在我将其添加到脚本时搞砸了。

    编辑

    正如 Mathias 所指出的,克隆 DOM 对象是最快的!这就是我在场景 #2 中所做的更改:

    //Scenario #2 : Clone DOM <li> element
           function cloneDOMLi() {
               var listElement = $("#listElementTemplate"); //pre cached the li so that it can be used again and again
               $.each(songs, function (i, song) {
                   $list.append(listElement.clone().text(song));
               });
    
               $list.listview("refresh");
           }
    

    并添加了一个额外的场景:

     function cloneDOMLiForLoop() {
       for(;i<songs.length; i++){
           //Cloned list element from already loaded dom element
           $listElement.clone().text(songs[i]);
           //Do some other stuff to listElement
           $list.append($listElement);
           //append to Displayed List
         };
    }
    

    看起来缓存 DOM li 成功了!正如前面(错误的)观察中提到的,for 在这种情况下也比each 快。结果:

    编辑 1 我又添加了一个测试,它只创建一次&lt;li&gt;&lt;/li&gt;,并在循环中克隆它。当然使用for 循环。这是代码:

    function makeLiProgrammaticallyOnceForLoop() {
         var li = $("<li></li>");
         for(;i<songs.length; i++){
           $list.append(li.clone().text(songs[i]));
         };
         $list.listview("refresh");
    }
    

    结果如下:

    看起来以编程方式创建li 并通过clone 重用它快。所以这些就不用说了:

    1. 您可以动态创建元素,也可以从 DOM 中获取它
    2. 预缓存您的元素并由clone 重复使用。
    3. 如果您想获得良好的性能,请使用 for 而不是 each

      重要 我没有在测试中提到 i-frame 方法,因为对于手机,尤其是运行 Android OS 2.3.7 的手机,在原生浏览器中有一个笨拙的 i-frame 实现,它避免它们总是好的,即使这可能是您最快的一种情况。

    【讨论】:

    • 有趣。如果在第二个测试用例(循环外)中缓存 $("#listElementTemplate") 会发生什么?我认为这可以更好地比较创建和克隆新元素,DOM 查找可能会扭曲结果。
    • 令人着迷,尽管我很难相信普通的for 循环和$.each 循环之间的区别是那么大Other tests 显示出更温和的差异。
    • 啊,我明白了:您在上次测试中错过了$list.listview("refresh");。这可能会产生很大的不同!
    • @MattiasBuelens 刚刚添加了listview(refresh) 并添加了更多测试,看看吧!也许是我的浏览器,for 一直比each 快。我正在使用 chrome 28。
    • 奇怪。我slightly reworked your tests(将东西从设置移到准备并删除了 jQuery Mobile CSS),我得到了不同的结果(在 Firefox 上)。
    猜你喜欢
    • 1970-01-01
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-16
    • 2020-06-22
    • 2010-09-18
    • 2012-02-05
    相关资源
    最近更新 更多