jQuery .html()与.append()的区别

270

假设我有一个空的div:

<div id='myDiv'></div>

这个是:

$('#myDiv').html("<div id='mySecondDiv'></div>");

与之相同:

var mySecondDiv=$("<div id='mySecondDiv'></div>");
$('#myDiv').append(mySecondDiv);

22
不,第二个没有ID,因此不会输出相同的文本。 - Matt Ellen
.html文件在第一次运行后速度会更快。第一次运行时可能需要一秒钟左右。 - sukhjit dhot
8个回答

338
无论何时您将HTML字符串传递给jQuery的任何方法,都会发生以下情况:
创建一个临时元素x,然后将x的innerHTML设置为您传递的HTML字符串。然后,jQuery将转移生成的每个节点(即x的childNodes)到一个新创建的文档片段中,并将其缓存以供下次使用。随后,它将返回该片段的childNodes作为新的DOM集合。
请注意,实际上比这复杂得多,因为jQuery会执行大量跨浏览器检查和各种其他优化。例如,如果您只传递<div></div>jQuery(),jQuery会采取捷径,简单地执行document.createElement('div')
编辑:要查看jQuery执行的大量检查,请参见此处此处此处
innerHTML通常是更快的方法,但不要总是依此决定。jQuery的方法不像element.innerHTML = ...那么简单 - 如我所述,会进行一系列的检查和优化。
正确的技术取决于具体情况。如果要创建大量相同的元素,则最后要做的就是创建一个巨大的循环,在每次迭代时创建一个新的jQuery对象。例如,使用jQuery快速创建100个divs的最佳方法:
jQuery(Array(101).join('<div></div>'));

还需要考虑可读性和维护性的问题。

这个:

$('<div id="' + someID + '" class="foobar">' + content + '</div>');

相对于这个,要维护起来很多更困难:

$('<div/>', {
    id: someID,
    className: 'foobar',
    html: content
});

7
为什么要使用101而不是100?jQuery(Array(101).join('<div></div>')); - tacone
2
只是想添加一个数据点。在对一个加载大量(10K+)<li>元素到<ul>中的应用程序进行性能测试时,通过将.append(giantListHTMLAsASingleString)切换为.html(giantListHTMLAsASingleString),看到了渲染时间(而不是加载时间)从约12秒增加到0.25秒。如果您已经使用“join”技巧或在列表上构建大型HTML字符串,则这两种方法之间肯定存在性能差异。 - omnisis
10
由于连接“粘合剂”是应用在数组元素之间的。像连接3个元素一样,101会有100个粘合剂被应用,就像EL-glue-EL-glue-EL会有2个粘合剂一样。在詹姆斯的例子中,数组元素是“空”的,所以连接N个空元素会导致N-1个连续的粘合剂。 - Fabrício Matté
6
对于那些对上面使用的jQuery语法感兴趣并想要了解其允许的内容,请参考http://api.jquery.com/jquery/#jQuery-html-attributes。 - Thaddeus Albers
1
在这一点上有一个很大的区别,它会丢失与DOM相关联的任何数据。 - Adrian Bartholomew
看起来你需要使用'class'(带引号)而不是className:由于“class”是JavaScript保留字,因此在对象中必须将其名称加上引号,并且不能使用“className”,因为它指的是DOM属性,而不是属性。http://api.jquery.com/jquery/#jQuery-html-attributes - SharpC

79

它们不是相同的。第一个 替换 HTML 而不需要先创建另一个 jQuery 对象。第二个则为第二个 div 创建了额外的 jQuery 封装器,然后将其 附加 到第一个上。

一个 jQuery 封装器(每个示例):

$("#myDiv").html('<div id="mySecondDiv"></div>');

$("#myDiv").append('<div id="mySecondDiv"></div>');

两个jQuery包装器(例如):

var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').html(mySecondDiv);

var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').append(mySecondDiv);

您有几种不同的用例。如果您想要替换内容, .html 是一个很好的选择,因为它等效于innerHTML = "..."。但是,如果您只想追加内容,则多余的$()包装器是不必要的。

只有在需要稍后操作添加的

时才使用两个包装器。即使在这种情况下,您仍然可能只需要使用一个:

var mySecondDiv = $("<div id='mySecondDiv'></div>").appendTo("#myDiv");
// other code here
mySecondDiv.hide();

你看到了吗?字符串连接已经导致了一个错误(未转义的引号)。看看我的帖子 :P - kizzx2

23

如果你所说的 .add 的意思是 .append,那么当 #myDiv 为空时,结果是相同的。

性能是否相同?不知道。

.html(x) 最终执行的操作与 .empty().append(x) 相同。


此外,第一个显然会有一个名为mySecondDiv的id,而另一个则没有。语法需要使用双引号".html("<div id='mySecondDiv'></div>")",以便能够使用单引号。 - ryanulit

11

.html() 将替换所有内容。

.append() 只会在末尾追加内容。


11

好的,.html() 使用比DOM创建更快的 .innerHTML


7
你可以通过以下方式获得第二种方法以实现相同的效果:
var mySecondDiv = $('<div></div>');
$(mySecondDiv).find('div').attr('id', 'mySecondDiv');
$('#myDiv').append(mySecondDiv);

Luca提到html()只是插入HTML,这样可以获得更快的性能。

但在某些情况下,你可能会选择第二个选项,请考虑:

// Clumsy string concat, error prone
$('#myDiv').html("<div style='width:'" + myWidth + "'px'>Lorem ipsum</div>");

// Isn't this a lot cleaner? (though longer)
var newDiv = $('<div></div>');
$(newDiv).find('div').css('width', myWidth);
$('#myDiv').append(newDiv);

5
这段jQuery代码效率极低(而且有缺陷)。如果你想避免字符串连接,可以这样写:(另外注意不需要添加 px):$('<div />', { width: myWidth }).appendTo("#myDiv"); - Doug Neiner
3
这个“不实用”是怎么回事?海报要求“区别”(关键字是“vs”),所以我告诉他们区别。代码很冗长,但我不会说它“低效”,仅仅因为它不是一行代码。当向人们解释东西时,我们难道不应该详细说明吗? - kizzx2

2

除了已经给出的答案,如果你遇到以下情况:

<div id="test">
    <input type="file" name="file0" onchange="changed()">
</div>
<script type="text/javascript">
    var isAllowed = true;
    function changed()
    {
        if (isAllowed)
        {
            var tmpHTML = $('#test').html();
            tmpHTML += "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
            $('#test').html(tmpHTML);
            isAllowed = false;
        }
    }
</script>

如果您想在上传了任何文件后自动添加一个文件上传,那么上述代码将无法正常工作,因为在文件上传后,第一个文件上传元素将被重新创建,因此上传的文件将从中删除。您应该使用 .append() 代替:

    function changed()
    {
        if (isAllowed)
        {
            var tmpHTML = "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
            $('#test').append(tmpHTML);
            isAllowed = false;
        }
    }

0
这种情况发生在我身上。Jquery版本:3.3。 如果您正在循环遍历对象列表,并希望将每个对象作为某个父DOM元素的子级添加,则.html和.append的行为将非常不同。.html最终只会将最后一个对象添加到父元素中,而.append将所有列表对象都添加为父元素的子级。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接