JQuery html () a innerHTML

81

Czy mogę całkowicie polegać na html()metodzie jQuery zachowującej się identycznie jak innerHTML? Czy jest jakaś różnica między metodą innerHTMLi jQuery html()? Jeśli obie te metody robią to samo, czy mogę użyć html()metody jQuery zamiast innerHTML?

Mój problem polega na tym, że pracuję na już zaprojektowanych stronach, strony zawierają tabele, aw JavaScript innerHTMLwłaściwość jest używana do ich dynamicznego wypełniania.

Aplikacja działa poprawnie na Firefox ale Internet Explorer odpala błąd: unknown runtime exception. Użyłem html()metody jQuery i błąd IE zniknął. Ale nie jestem pewien, czy zadziała we wszystkich przeglądarkach i nie jestem pewien, czy zastąpić wszystkie innerHTMLwłaściwości html()metodą jQuery .

Wielkie dzięki.

Bhupi
źródło
9
użyj jQuery html (). Wielokrotnie miałem problemy z innerHTML. A html () będzie działać we wszystkich przeglądarkach.
Glavić,

Odpowiedzi:

118

Odpowiedzieć na Twoje pytanie:

.html()po prostu zadzwoni .innerHTMLpo sprawdzeniu typów węzłów i innych rzeczy. Używa również try/catchbloku, w którym próbuje użyć jako innerHTMLpierwszy, a jeśli to się nie powiedzie, z wdziękiem powróci do .empty()+append()

jAndy
źródło
13
Zauważ, że w przypadku Internet Explorera 8 (i najprawdopodobniej wcześniej) dodatkowe testy mogą znacząco wpłynąć na wydajność dużych wstawek, więc jeśli wydajność w IE jest ważna, możesz rozważyć użycie innerHTMLbezpośrednio.
sroebuck
3
Zwięzłe porównanie wydajności: jsperf.com/innerhtml-vs-html-vs-empty-append
thdoan
17

W szczególności w odniesieniu do „Czy mogę całkowicie polegać na metodzie jquery html (), która będzie działać jak innerHTML”, moja odpowiedź brzmi NIE!

Uruchom to w programie Internet Explorer 7 lub 8, a zobaczysz.

jQuery generuje zły kod HTML podczas ustawiania kodu HTML zawierającego tag <FORM> zagnieżdżony w tagu <P>, gdzie początek ciągu jest znakiem nowej linii!

Jest tutaj kilka przypadków testowych, a komentarze po uruchomieniu powinny być wystarczająco zrozumiałe. Jest to dość niejasne, ale niezrozumienie tego, co się dzieje, jest trochę niepokojące. Mam zamiar zgłosić błąd.

<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
źródło
Myślę, że ten raport o błędzie wrócił, mówiąc mi, że mam nieprawidłowy kod HTML w odniesieniu do tego, co jest dozwolone w tagu <P> - lub coś w tym rodzaju. to było dość dawno, więc nie jestem pewien, czy coś się zmieniło, ale 3 lata później wciąż pojawiają się głosy, więc jeśli ktoś ma coś do dodania, dodaj komentarz
Simon_Weaver
To jest nadal w IE9, po prostu spróbuj z tym: $ ("body"). Html ("<p> <form> <div> Widzisz, co tam zrobiłem? </div> </form> </p>" );
Superzadeh
8

Jeśli zastanawiasz się nad funkcjonalnością, to jQuery .html()wykonuje te same zamierzone funkcje co .innerHTML, ale sprawdza również zgodność z różnymi przeglądarkami.

Z tego powodu zawsze możesz użyć jQuery .html()zamiast .innerHTMLtam, gdzie to możliwe.

David Tang
źródło
2
innerHTML jest właściwością dokumentu / elementu, a nie metodą.
Satish N Ramteare
6

innerHTML nie jest standardem i może nie działać w niektórych przeglądarkach. Użyłem html () we wszystkich przeglądarkach bez problemu.

Craig
źródło
3
jest teraz standardem (nie wiem, kiedy zadawano pytanie): domparsing.spec.whatwg.org/#innerhtml
griffin
3

Biorąc pod uwagę ogólne wsparcie w.innerHTML dzisiejszych czasach, jedyną skuteczną różnicą jest teraz to, że .html()będzie wykonywał kod w dowolnych <script>tagach, jeśli są jakieś w podanym html. .innerHTML, Pod HTML5 , nie będzie.

Z dokumentacji jQuery :

Z założenia każdy konstruktor lub metoda jQuery, która akceptuje ciąg znaków HTML - jQuery (), .append (), .after () itd. - może potencjalnie wykonać kod. Może to nastąpić przez wstrzyknięcie znaczników skryptów lub użycie atrybutów HTML, które wykonują kod (na przykład <img onload="">). Nie używaj tych metod do wstawiania ciągów uzyskanych z niezaufanych źródeł, takich jak parametry zapytań URL, pliki cookie lub dane wejściowe formularzy. Może to spowodować powstanie luk w zabezpieczeniach cross-site-scripting (XSS). Usuń wszelkie dane wejściowe użytkownika lub usuń je przed dodaniem treści do dokumentu.

Uwaga: oba .innerHTMLi .html()mogą wykonywać js w inny sposób (np. onerrorAtrybut).

RedRiderX
źródło
Bardzo interesujące. Jak więc możemy zmusić HTML5 do wykonywania tagów <script> po wstawieniu?
aizquier
Jest trochę stary, ale nadal uważam, że rozwiązanie innej odpowiedzi działałoby dzisiaj dobrze. Jeśli używasz jQuery, możesz oczywiście po prostu użyć .html ().
RedRiderX
Teraz, gdy spojrzę na to ponownie, w tej odpowiedzi brakuje kroku parsowania scripttagów z większego fragmentu html. Może potrzebne jest nowe pytanie / odpowiedź?
RedRiderX
0

Oto kod na dobry początek. Możesz modyfikować zachowanie .innerHTML - możesz nawet stworzyć własną kompletną podkładkę .innerHTML. (PS: przedefiniowanie .innerHTML będzie działać również w przeglądarce Firefox, ale nie w Chrome - pracują nad tym).

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
źródło