1

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

方法#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");
    
  • 4

    1 回答 1

    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");
       }
    

    最后一个场景是我的补充,只是为了检查是否foreach这个场景更好。结果是..击鼓

    结果

    jsPerf 结果

    看起来像以<li>编程方式添加,循环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
         };
    }
    

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

    修改后的 jsPerf

    编辑 1 我添加了一个<li></li>只创建一次的测试,并在循环中克隆它。当然使用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 实现,避免它们总是好的,即使这可能成为最快的场景之一。

    于 2013-07-13T11:06:19.377 回答