Beim Versuch herauszufinden, warum eine Seite 20s zum Laden benötigt, habe ich ein merkwürdiges Verhalten in IE8 festgestellt.
Das Szenario ist das.
Ich mache einen Ajax-Aufruf, es kehrt zurück und der Callback sah ungefähr so aus
%Vor%Dieses Codebeispiel dauerte jedoch 20 Sekunden.
Ich habe herumgespielt, Dinge getimt und Warnungen zwischen Methoden ausgegeben, und plötzlich waren es nur noch sechs Sekunden. Ich habe ein wenig mehr herumgespielt, um zu sehen, dass, wenn ich eine Verzögerung nach dem Aufruf von .html()
einführte und bevor ich versuchte, das DOM zu manipulieren, die Seite VIEL schneller wurde. Es sieht jetzt so aus
Es dauert auch nur 6s, obwohl eine zusätzliche 1/10 Sekunde zum Prozess hinzugefügt wurde.
Meine Theorie ist, dass, weil das DOM nicht vollständig vom IE mit dem .html()
-Aufruf auf den Bildschirm gerendert wurde, bevor versucht wird, damit zu arbeiten, eine Art Locking stattfindet.
Gibt es eine Möglichkeit zu bestimmen, wann der IE das Rendering von dem, was vom .html()
zum DOM hinzugefügt wurde, fertig ist, so dass ich keinen willkürlichen Wert in einem setTimeout
-Aufruf verwenden muss?
Sie können Ihrer Callback-Antwort ein einzelnes Pixelbild hinzufügen, dieses Image aus dem DOM nach .html (..) abrufen und an sein onload-Ereignis anhängen. Ich kann mir nicht vorstellen, dass das Onload-Ereignis des Bildes ausgelöst werden kann, bis der Browser es gerendert hat.
Stellen Sie sicher, dass das Bild im src eine eindeutige Kennung hat, damit es nicht zwischengespeichert wird ...
Seltsames Problem, das Sie haben - ich bin sicher, dass jemand eine elegantere Lösung anbieten wird:)
B
Sie sind mit Ihrer Analyse fast auf der Stelle. Lassen Sie mich versuchen zu erklären, warum setTimeout
den Unterschied macht.
Wenn Sie sich diesen großartigen Artikel zum DOM-Rendering ansehen Sie werden verstehen, dass .html()
zu einem Reflow führt.
Nun, mit den nächsten zwei Zeilen, was passiert ist, dass Sie den Rendering-Thread des Browsers binden. Browser können warten, bis die Ausführung des Skripts abgeschlossen ist, bevor ein Reflow-Vorgang durchgeführt wird (um mehrfache Reflow-Vorgänge zu vermeiden oder alle Änderungen zwischenzuspeichern).
Die Lösung - wir müssen dem Browser mitteilen, dass unsere html
Änderungen vorgenommen wurden und Sie den Rendering-Prozess abschließen können. Die Art und Weise es zu tun - 1) beenden Sie Ihr Skript 2) Verwenden Sie setTimeout
, um die Ausführung an den Browser zu liefern.
Das Ausführen einer setTimeout
mit 0ms Verzögerung funktioniert auch, weil setTimeout
grundsätzlich die Kontrolle über den Quellblock abgibt. Einer der Gründe, warum animationsbezogene Skripte so stark auf setTimeout
und setInterval
beruhen.
Eine weitere mögliche Verbesserung wäre die Verwendung von documentFragments
, was John Resig hier
Ich denke, das Kombinieren dieser beiden sollte mehr Geschwindigkeit ergeben, aber natürlich keine Möglichkeit zu wissen, bis das Profiling fertig ist!
Das Aufrufen von setTimeout
verzögert die angegebene Funktion mindestens für die angegebene Zeit, aber sie wird nie ausgeführt, bevor die aktuelle Skriptausführung abgeschlossen ist. Das heißt, Sie könnten Ihr Timeout durch 0 Sekunden ersetzen.
Ein anderer Ansatz, den Sie vielleicht ausprobieren sollten, besteht darin, dass Sie auf eine Layouteigenschaft des generierten Inhalts zugreifen (z. B. Höhe von StoreDetailsContainer ). Auf diese Weise erzwingen Sie, dass der IE das Rendering beendet, bevor er die Kontrolle an Ihr Skript zurückgibt, da er nur den korrekten Wert bereitstellen kann, den Ihr Skript nach der Berechnung des Layouts angefordert hat.
Die dritte Möglichkeit, die Ihnen helfen könnte, ist, dass Sie sicherstellen, dass Sie den HTML-Code mit dem Seitenlayout analysieren. Dies würde verhindern, dass halb fertiggestellte Layouts immer wieder neu gezeichnet werden. Um dies zu tun, können Sie das Element StoreDetailsContainer vor dem Aufruf von html
vom DOM trennen. Jetzt hat IE die Änderung, um das DOM zu konstruieren, ohne das Layout zu beeinflussen. Danach fügen Sie den StoreDetailsContainer erneut in das DOM ein. Im Vergleich zu einem normalen innerHTML
-Satz ermöglicht dieses Trennen und erneute Anhängen des Containers, dass Sie steuern, wann der HTML-Code analysiert wird, um den DOM-Baum zu erstellen, und wann das Layout berechnet wird.
Probieren Sie diesen Code aus. Das load-Ereignis wird nach dem ready-Ereignis ausgelöst, sodass es funktioniert.
%Vor%Tags und Links javascript jquery dom internet-explorer-8