动态添加/删除HTML时防止内存泄漏

时间:2012-07-11 21:26:45

标签: javascript jquery jquery-mobile

我正在使用PhoneGap和JQuery Mobile创建一个应用程序,我期望从一些后端服务读取数据,并根据收到的内容添加/删除列表项(也可能是div)。当然,我希望防止应用程序长时间使用减慢太多。

添加/删除HTML时是否有一般的最佳做法?我对此很陌生,所以我真的不明白DOM是如何工作的等等。

目前我正在使用JQuery的附加功能将HTML行添加到某个容器div中,并使用.html(“”)删除元素。这是可以接受的,还是有更好的方法呢?

编辑:供您参考,我使用的是JQuery Mobile 1.1.0和Phonegap 1.9.0。不知道这是否有用,但你去了。

我希望在尽可能多的移动设备上使用此应用程序,但我猜iOS和Android现在是最大的市场。

为了澄清,我实际上还没有遇到过主要问题(我),我只是想避免以后遇到任何问题,并且必须通过大量代码来尝试解决问题。我认为如果我们能够就一组最佳实践达成一致意见对它们有用,即使用innerHTML()而不是.append,remove vs innerHTML(“”),et cetra:P

一些示例代码:

function changeList(sel){
            var xmlfolder="/"
            var name = sel[sel.selectedIndex].value+".xml";                
            var location= xmlfolder+name;
            var list = document.getElementById("opList"); //opList is the container
            list.innerHTML=""; //what i'm using to remove the previous occupant
                               //: is there a better way of doing this?
            //reading stuff                
            $.ajax({

                type:'GET',
                cache: false,
                url: location,
                dataType:"xml",
                success: function(data){
                    xmlInfo=data;


                    var i=0;
                    $(data).find("data").each(function(){

                        var string = "";
                        var sName=$(this).find("name").text();

                        string +=("<li>");
                        string +=("<a href=#details data-transition = slide >");
                        string+= sName;
                        string+="</a></li>";
                         $('#opList').append(string); //is there a better way of appending?
                         i++;

                    })

                    $('#opList').listview('refresh');

                },                    
                error:function(e){
                    alert("failed D:");
                    console.log(e);
                }

            });

        }

1 个答案:

答案 0 :(得分:4)

我只想向你抛出一些想法,我们会看到什么棒!

确保编制HTML并将其一次性添加到DOM中,而不是在循环或其他内容中添加碎片。

例如(DO THIS):

var arr    = ['Title 1', 'Title 2', 'Title 3'],
    output = [];

for (var i = 0, len = arr.length; i < len; i++) {
    output.push('<li>' + arr[i] + '</li>');
}
$('ul').append(output.join(''));

注意我只选择一次容器,这是关键,即使你必须在循环中引用一个DOM元素,确保缓存对循环外元素的引用,否则你不必要地做额外的每次迭代都要工作。

例如(不要这样做,除了DOM元素缓存,这很好):

var arr = ['Title 1', 'Title 2', 'Title 3'],
    $ul = $('ul');

for (var i = 0, len = arr.length; i < len; i++) {
    $ul.append('<li>' + arr[i] + '</li>');
}

如果要向DOM添加一些复杂的HTML结构,请执行与以前相同的操作,创建“临时”容器,对其执行操作,然后立即将整个内容附加到DOM。例如:

var $tmpObj = $('<div id="my-div" />').append(
    $('<span class="my-title" />').text('Title 1')
).append(
    $('<div class="my-description" />').append(
        $('<span class="my-copy" />').text('Blah Blah Blah')
    )
).on('click', function () {
    alert('Don\'t Touch Me!');
}).data('my-data-key', 'my-data-val');

$('#my-div').replaceWith($tmpObj);

我喜欢使用$.data()存储与对象关联的数据,这样当一个元素被删除时,它的数据就会被删除,因此我们不会使用无用数据的内存。

使用JSPerf.com,如果使用得当,这是一个了不起的工具。您可以运行测试以确定哪种方法更快地进行操作。以下是我之前设置的示例:http://jsperf.com/jquery-each-vs-for-loops/2

不要不必要地创建全局变量。执行此操作时,在查找这些变量时会产生额外的开销。这一行:xmlInfo=data;应为var xmlInfo=data;,除非在AJAX回调函数之外访问xmlInfo。基本上,当您在函数内部(或嵌套函数)查找全局范围内的变量时;首先,浏览器将查看当前范围,然后查看当前范围的父范围,一直到全局范围。因此,如果您尝试在函数内部的函数内部访问全局变量,那么您现在所做的查找量就像使用本地范围的变量一样多三倍。如果必须使用全局范围的变量,请将其缓存在函数内部并使用函数中的本地版本以避免额外的循环时间。