jQuery html()与innerHTML


80

我是否可以完全依赖jQuery的html()行为方式与相同innerHTMLinnerHTML和jQuery的html()方法之间有什么区别吗?如果这些方法都相同,是否可以使用jQuery的html()方法代替innerHTML

我的问题是:我正在设计的页面上工作,这些页面包含表格,并且在JavaScript中,该innerHTML属性用于动态填充它们。

该应用程序在Firefox上运行正常,但是Internet Explorer会引发错误:unknown runtime exception。我使用jQuery的html()方法,而IE的错误已消失。但是我不确定它是否适用于所有浏览器,也不确定是否innerHTML用jQuery的html()方法替换所有属性。

非常感谢。


9
使用jQuery html()。我在很多情况下都遇到了innerHTML问题。html()将在所有浏览器上运行。
Glavić

Answers:


116

要回答您的问题:

.html().innerHTML在检查完nodeTypes和东西之后才会调用。它还try/catch在尝试innerHTML首先使用的地方使用一个块,如果失败,它将优雅地回退到jQuery的.empty()+append()


13
请注意,使用Internet Explorer 8(并且很可能是更早的版本),附加检查可能会给大型插入增加明显的性能影响,因此,如果IE上的性能很重要,则您可能需要考虑innerHTML直接使用。
sroebuck


17

特别是关于“我可以完全依赖于它会像innerHTML一样执行的jQuery html()方法”时,我的回答是否定的!

在Internet Explorer 7或8中运行此命令,您将看到。

设置包含嵌套在<P>标记内的<FORM>标记的HTML时,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>

I think this bug report came back as telling me I had invalid HTML with respect to what was allowed in a <P> tag - or something like that. this was quite a while ago so I'm not sure if anything changed, but this is still getting upvotes 3 years later so if anyone has anything to add please add a comment
Simon_Weaver

This is still here in IE9, just try with that: $("body").html("<p><form><div>See what I did there ?</div></form></p>");
Superzadeh

8

If you're wondering about functionality, then jQuery's .html() performs the same intended functionality as .innerHTML, but it also performs checks for cross-browser compatibility.

For this reason, you can always use jQuery's .html() instead of .innerHTML where possible.


2
innerHTML is a property on document/element property and not a method.
Satish N Ramteare



3

Given the general support of .innerHTML these days, the only effective difference now is that .html() will execute code in any <script> tags if there are any in the html you give it. .innerHTML, under HTML5, will not.

From the jQuery docs:

By design, any jQuery constructor or method that accepts an HTML string — jQuery(), .append(), .after(), etc. — can potentially execute code. This can occur by injection of script tags or use of HTML attributes that execute code (for example, <img onload="">). Do not use these methods to insert strings obtained from untrusted sources such as URL query parameters, cookies, or form inputs. Doing so can introduce cross-site-scripting (XSS) vulnerabilities. Remove or escape any user input before adding content to the document.

Note: both .innerHTML and .html() can execute js other ways (e.g the onerror attribute).


Very interesting. So how can we force HTML5 to execute <script> tags when inserted?
aizquier

It's a bit old but I still think another answer's solution would work well today. You could of course just use .html() if you're using jQuery.
RedRiderX

Now that I look at it again, that answer does miss the step of parsing script tags out of a larger html fragment. Maybe a new question/answer is in order?
RedRiderX

0

Here is some code to get you started. You can modify the behavior of .innerHTML -- you could even create your own complete .innerHTML shim. (P.S.: redefining .innerHTML will also work in Firefox, but not Chrome -- they're working on it.)

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/

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.