JQuery html () frente a innerHTML

81

¿Puedo confiar completamente en que el html()método de jQuery se comporta de manera idéntica innerHTML? ¿Hay alguna diferencia entre innerHTMLel html()método y jQuery ? Si ambos métodos hacen lo mismo, ¿puedo usar el html()método de jQuery en lugar de innerHTML?

Mi problema es: estoy trabajando en páginas ya diseñadas, las páginas contienen tablas y en JavaScript la innerHTMLpropiedad se usa para poblarlas dinámicamente.

La aplicación está funcionando bien en Firefox pero Internet Explorer dispara un error: unknown runtime exception. Usé el html()método de jQuery y el error de IE ha desaparecido. Pero no estoy seguro de que funcione para todos los navegadores y no estoy seguro de si reemplazar todas las innerHTMLpropiedades con el html()método de jQuery .

Muchas gracias.

Bhupi
fuente
9
use jQuery html (). Tuve problemas con innerHTML en muchas ocasiones. Y html () funcionará en todos los navegadores.
Glavić

Respuestas:

118

Para responder tu pregunta:

.html()simplemente llamará .innerHTMLdespués de hacer algunas comprobaciones de nodeTypes y demás. También usa un try/catchbloque donde intenta usar innerHTMLprimero y, si eso falla, recurrirá con gracia a jQuery's .empty()+append()

jAndy
fuente
13
Tenga en cuenta que con Internet Explorer 8 (y probablemente antes) las comprobaciones adicionales pueden agregar un impacto de rendimiento significativo para inserciones grandes, por lo que si el rendimiento en IE es importante, puede considerar usarlo innerHTMLdirectamente.
sroebuck
3
Una comparación de rendimiento concisa: jsperf.com/innerhtml-vs-html-vs-empty-append
thdoan
17

Específicamente con respecto a "¿Puedo confiar completamente en el método jquery html () que funcionará como innerHTML", mi respuesta es NO!

Ejecute esto en Internet Explorer 7 u 8 y verá.

jQuery produce un HTML incorrecto al configurar HTML que contiene una etiqueta <FORM> anidada dentro de una etiqueta <P> donde el comienzo de la cadena es una nueva línea.

Hay varios casos de prueba aquí y los comentarios cuando se ejecutan deben ser lo suficientemente autoexplicativos. Esto es bastante oscuro, pero no entender lo que está pasando es un poco desconcertante. Voy a presentar un informe de error.

<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>
Simon_Weaver
fuente
Creo que este informe de error me dijo que tenía HTML no válido con respecto a lo que estaba permitido en una etiqueta <P>, o algo por el estilo. esto fue hace bastante tiempo, así que no estoy seguro de si algo cambió, pero esto todavía está recibiendo votos positivos 3 años después, así que si alguien tiene algo que agregar, agregue un comentario
Simon_Weaver
Esto todavía está aquí en IE9, solo intente con eso: $ ("body"). Html ("<p> <form> <div> ¿Ves lo que hice allí? </div> </form> </p>" );
Superzadeh
8

Si se está preguntando acerca de la funcionalidad, entonces jQuery .html()realiza la misma funcionalidad prevista que .innerHTML, pero también realiza verificaciones de compatibilidad entre navegadores.

Por esta razón, siempre puede usar jQuery en .html()lugar de .innerHTMLcuando sea posible.

David Tang
fuente
2
innerHTML es una propiedad de la propiedad de documento / elemento y no un método.
Satish N Ramteare
6

innerHTML no es estándar y puede que no funcione en algunos navegadores. He usado html () en todos los navegadores sin problema.

Craig
fuente
3
es estándar ahora (no sé cuándo
griffin
3

Teniendo en cuenta el apoyo general de.innerHTML estos días, la diferencia sólo es eficaz ahora es que .html()se ejecute código en cualquier <script>etiquetas si hay alguno en el html que le des. .innerHTML, en HTML5 , no lo hará.

De los documentos de jQuery :

Por diseño, cualquier constructor o método de jQuery que acepte una cadena HTML (jQuery (), .append (), .after (), etc.) puede potencialmente ejecutar código. Esto puede ocurrir mediante la inyección de etiquetas de secuencia de comandos o el uso de atributos HTML que ejecutan código (por ejemplo, <img onload="">). No utilice estos métodos para insertar cadenas obtenidas de fuentes no confiables, como parámetros de consulta de URL, cookies o entradas de formulario. Hacerlo puede introducir vulnerabilidades de secuencias de comandos entre sitios (XSS). Elimine o escape cualquier entrada del usuario antes de agregar contenido al documento.

Nota: ambos .innerHTMLy .html()pueden ejecutar js de otras formas (por ejemplo, el onerroratributo).

RedRiderX
fuente
Muy interesante. Entonces, ¿cómo podemos obligar a HTML5 a ejecutar etiquetas <script> cuando se insertan?
aizquier
Es un poco antiguo, pero todavía creo que la solución de otra respuesta funcionaría bien hoy. Por supuesto, podría usar .html () si está usando jQuery.
RedRiderX
Ahora que lo miro de nuevo, esa respuesta pierde el paso de analizar las scriptetiquetas de un fragmento html más grande. ¿Quizás una nueva pregunta / respuesta esté en orden?
RedRiderX
0

Aquí hay un código para comenzar. Puede modificar el comportamiento de .innerHTML, incluso puede crear su propio shim .innerHTML completo. (PD: redefinir .innerHTML también funcionará en Firefox, pero no en Chrome, están trabajando en eso).

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/

Agamemnus
fuente