JQuery html()与innerHTML有何不同?

86
我可以完全信赖jQuery的html()方法与innerHTML的行为完全相同吗?innerHTML和jQuery的html()方法之间有什么区别?如果这些方法都做同样的事情,我可以使用jQuery的html()方法来替换innerHTML吗?
我的问题是:我正在处理已设计好的页面,这些页面包含表格,在JavaScript中使用innerHTML属性动态填充它们。应用程序在Firefox上运行良好,但在Internet Explorer上会出现错误:未知的运行时异常。我使用了jQuery的html()方法,IE的错误消失了。但我不确定它是否适用于所有浏览器,也不确定是否要将所有的innerHTML属性替换为jQuery的html()方法。
非常感谢。

9
使用jQuery的html()方法。我在许多情况下都与innerHTML遇到了问题。而html()方法在所有浏览器上都能正常工作。 - Glavić
8个回答

124
回答您的问题: .html()方法只是在执行节点类型和其他检查后调用.innerHTML方法。它还使用try/catch块,首先尝试使用innerHTML,如果失败,它会优雅地回退到jQuery的.empty() + append()方法。

13
请注意,在使用Internet Explorer 8(以及很可能是更早版本)时,额外的检查可能会为大量插入操作带来显著的性能影响,因此如果在IE上的性能很重要,您可能需要考虑直接使用innerHTML - sroebuck
3
简洁的性能比较:http://jsperf.com/innerhtml-vs-html-vs-empty-append - thdoan

17

关于“我能完全依赖jquery html()方法,让它像innerHTML一样工作吗?”我的回答是NO!

在Internet Explorer 7或8中运行此代码,您会看到问题。

当将包含<FORM>标签的HTML设置为<P>标签中嵌套时,jQuery会生成糟糕的HTML,其中字符串开头是换行符!

此处有几个测试用例,运行时的注释应该足够自我解释。这很难理解,但不了解发生了什么有点令人不安。我将提交一个错误报告。

<html>

    <head>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>   

        <script>
            $(function() {

                // the following two blocks of HTML are identical except the P tag is outside the form in the first case
                var html1 = "<p><form id='form1'><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></form></p>";
                var html2 = "<form id='form1'><p><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></p></form>";

                // <FORM> tag nested within <P>
                RunTest("<FORM> tag nested within <P> tag", html1);                 // succeeds in Internet Explorer    
                RunTest("<FORM> tag nested within <P> tag with leading newline", "\n" + html1);     // fails with added new line in Internet Explorer


                // <P> tag nested within <HTML>
                RunTest("<P> tag nested within <FORM> tag", html2);                 // succeeds in Internet Explorer
                RunTest("<P> tag nested within <FORM> tag with leading newline", "\n" + html2);     // succeeds in Internet Explorer even with \n

            });

            function RunTest(testName, html) {

                // run with jQuery
                $("#placeholder").html(html);
                var jqueryDOM = $('#placeholder').html();
                var jqueryFormSerialize = $("#placeholder form").serialize();

                // run with innerHTML
                $("#placeholder")[0].innerHTML = html;

                var innerHTMLDOM = $('#placeholder').html();
                var innerHTMLFormSerialize = $("#placeholder form").serialize();

                var expectedSerializedValue = "field1=111&field2=222";

                alert(  'TEST NAME: ' + testName + '\n\n' +
                    'The HTML :\n"' + html + '"\n\n' +
                    'looks like this in the DOM when assigned with jQuery.html() :\n"' + jqueryDOM + '"\n\n' +
                    'and looks like this in the DOM when assigned with innerHTML :\n"' + innerHTMLDOM + '"\n\n' +

                    'We expect the form to serialize with jQuery.serialize() to be "' + expectedSerializedValue + '"\n\n' +

                    'When using jQuery to initially set the DOM the serialized value is :\n"' + jqueryFormSerialize + '\n' +
                    'When using innerHTML to initially set the DOM the serialized value is :\n"' + innerHTMLFormSerialize + '\n\n' +

                    'jQuery test : ' + (jqueryFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") + '\n' +
                    'InnerHTML test : ' + (innerHTMLFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") 

                    );
            }

        </script>
    </head>

    <div id="placeholder">
        This is #placeholder text will 
    </div>

</html>

我认为这个错误报告告诉我在<P>标签中使用了不允许的HTML,或者类似的内容。这是很久以前的事情了,所以我不确定是否有任何改变,但是三年后它仍然得到了赞同,如果有人有什么要补充的,请添加评论。 - Simon_Weaver
这在IE9中仍然存在,只需尝试:$("body").html("<p><form><div>看到我做了什么吗?</div></form></p>"); - Superzadeh

8
如果您想了解功能,那么jQuery的.html().innerHTML具有相同的预期功能,但它还会检查跨浏览器兼容性。
因此,在可能的情况下,您始终可以使用jQuery的.html()代替.innerHTML

2
innerHTML是文档/元素属性上的一个属性,而不是一个方法。 - Satish N Ramteare

6

innerHTML不是标准的,在一些浏览器中可能无法正常工作。我在所有浏览器中都使用了html(),没有任何问题。


3
现在已经成为标准了(不确定提问时的时间):http://domparsing.spec.whatwg.org/#innerhtml - griffin

5
这些天来,鉴于.innerHTML的广泛支持, 现在唯一有效的区别是.html()将在你提供的HTML中执行任何<script>标签中的代码。而在HTML5中.innerHTML则不会执行。
jQuery文档中可以看到:
引用: 设计上,任何接受HTML字符串的jQuery构造函数或方法(例如jQuery()、.append()、.after()等)都可能执行代码。这可以通过注入脚本标记或使用执行代码的HTML属性(例如<img onload="">)来实现。不要使用这些方法插入从不受信任的来源获取的字符串,例如URL查询参数、cookies或表单输入。这样做可能会引入跨站点脚本(XSS)漏洞。在添加内容到文档之前,请删除或转义任何用户输入。
注意:无论是.innerHTML还是.html()都可以执行其他方式的js(例如onerror属性)。

1
非常有趣。那么我们如何强制HTML5在插入时执行<script>标签? - aizquier
1
这个解决方案有点老了,但我仍然认为另一个答案的解决方案今天仍然适用。当然,如果你正在使用jQuery,你可以直接使用.html()。 - RedRiderX
1
现在我再看一遍,那个答案确实漏掉了从较大的HTML片段中解析“script”标签的步骤。也许需要一个新的问题/答案? - RedRiderX
处理脚本元素:在早期版本的jQuery中,html()方法会执行通过该方法设置的HTML中找到的任何<script>元素。在jQuery 3.0中,这种行为已经改变,除非将html()方法的第三个参数显式设置为true,否则默认情况下不会执行HTML中存在的任何脚本。 - leoneboaventura

3

0

这里有一些代码可以帮助你入门。你可以修改 .innerHTML 的行为,甚至可以创建自己完整的 .innerHTML 代理。(附注:重新定义 .innerHTML 在 Firefox 中也可以工作,但在 Chrome 中不行——他们正在解决这个问题。)

if (/(msie|trident)/i.test(navigator.userAgent)) {
 var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
 var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
 Object.defineProperty(HTMLElement.prototype, "innerHTML", {
  get: function () {return innerhtml_get.call (this)},
  set: function(new_html) {
   var childNodes = this.childNodes
   for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
    this.removeChild (childNodes[0])
   }
   innerhtml_set.call (this, new_html)
  }
 })
}

var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)

document.body.innerHTML = ""
console.log (mydiv.innerHTML)

http://jsfiddle.net/DLLbc/9/


-1
一个关键的区别是jQuery的.html()方法会执行HTML内部的任何行内<script>标签。
这对我来说非常重要,因为我正在使用fetch请求获取一个包含<script>标签的HTML响应,以使WordPress中的模态框正常工作。但它没有起作用,我把问题缩小到了.html().innerHTML之间,我认为它们是相同的。在控制台记录响应并将其复制到文件中搜索<script>后,我发现只有.html()才能运行代码,而.innerHTML则不能。
还有像jAndy提到的类型检查。
要执行脚本,请参阅RedRiderX在上面评论中链接的此问题:如何运行通过ajax加载的html中的javascript

jQuery .html() 文档并不是针对这个特定问题非常有帮助:https://api.jquery.com/html/


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