在jQuery Mobile中动态生成列表的最快方法是什么?

时间:2013-07-12 22:09:00

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

我正在创建一个jQuery移动应用程序,其中UI事件即时生成列表。因此,我可以更快地制作这些列表,我的UI将显示得越快。我在下面概述了几种方法。我希望拥有网络性能专业知识的人可以告诉我他们认为哪种方法最好,或者建议采用全新的方法。

方法#1“Programaticaly从列表元素对象数组生成

  • 选择器”

    $.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“Clone

  • 来自列表元素对象数组的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");
    
  • 1 个答案:

    答案 0 :(得分: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。结果是...... 鼓声

    结果

    jsPerf result

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

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

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

    以下是结果:

    enter image description here

    看起来以编程方式创建li并通过clone重复使用。所以这些不言而喻:

    1. 您可以动态创建元素,也可以从DOM中获取元素
    2. 预先缓存您的元素并按clone重复使用。
    3. 如果您想获得良好的效果,请使用for代替each

      重要我没有在测试中提到i-frame方法,因为对于手机,尤其是运行Android OS 2.3.7的手机,在本机浏览器中有一个笨重的i-frames实现,总是很好避免它们,即使这可能是你最快的场景之一。