Normalerweise verwende ich domReady() -Funktionen (entweder jQuerys oder handgemachte), wenn ich Code ausführen möchte, nachdem ich sicher bin, dass das DOM der Seite vollständig geladen wurde (99% der Fälle sind Initialisierungscode).

Jetzt muss ich eine HTML-Vorlage in ein DIV-Element einfügen, aber danach muss ich einige Elemente, die hinzugefügt wurden, abrufen und bearbeiten (Texte ändern, Ereignisse anhängen, Validierungsnachrichten und Masken festlegen usw.).

div.innerHTML += htmlTemplate; // Template which has the "someInput" input
var someInput = document.getElementById('someInput');

Die Sache ist: Ist es sicher anzunehmen, dass das input in DOM geladen wurde? Muss ich nach dem Anhängen des HTML-Codes an den DIV den Code, der auf den neuen DOM-Elementen basiert, als Rückruf an die Funktion domReady senden?

div.innerHTML += htmlTemplate;
domReady(function(){
    var someInput = document.getElementById('someInput');
    // ...
});

Technisch gesehen ... Jedes Mal, wenn einfaches HTML zu Elementen hinzugefügt wird, wechselt das DOM in den Ladezustand?

- BEARBEITEN

Hier ist die domReady () -Funktion, die ich verwende:

function domReady(f) {
    /in/.test(document.readyState) ? setTimeout('domReady('+f+')', 9) : f();
}

PS: Ich brauchte eine einfache / kurze / nicht API-abhängige Funktion, also bin ich vor einiger Zeit in SE auf diese gestoßen.

Danke im Voraus.

3
everton 4 Dez. 2013 im 21:10

3 Antworten

Beste Antwort

Tritt das DOM jedes Mal in den Ladezustand ein, wenn den Elementen einfaches HTML hinzugefügt wird?

Nein, das tut es nicht. Sie können sich darauf verlassen, dass die Elemente direkt nach dem Ende des innerHTML= -Aufrufs vorhanden sind. Schauen Sie sich diesen jsbin an, in dem ich 1 Sekunde lang <li> Elemente mit innerHTML hinzufüge. und überprüfen Sie jedes Mal, wenn die vorherigen Elemente vorhanden sind, mit .querySelectorAll.

Die Einstellung element.innerHTML ist synchron: Der Browser stoppt alles, was er tut, um das DOM entsprechend zu aktualisieren (was nicht bedeutet, dass die Seite visuell aktualisiert wird, wie aus dem Beispiel hervorgeht, auf das ich verlinkt habe), und die Steuerung funktioniert nicht. t Kehren Sie zu Ihrem Code zurück, bis er fertig ist.


Beispiel für Manipulationen in einem getrennten DOM-Knoten:

var tempDiv = document.createElement("div");
tempDiv.innerHTML = getTemplateSomehow();

// Manipulate a button inside the template,
// even though it is not in the DOM yet
var button = tempDiv.querySelector("button");
button.style.color = "red";
button.addEventListener("click", function() {
  alert("button clicked");
});

// Append all children from the parsed template into the DOM
var child;
var target = document.body;

// Keep moving tempDiv's children to the target until it is empty
while(child = tempDiv.firstChild) {
  target.appendChild(child);
}

Arbeitsbeispiel: http://jsbin.com/isuLeMi/1/edit

4
Renato Zannon 6 Dez. 2013 im 19:08

Wenn Sie über ein Onload-Ereignis in domReady sprechen, wird dieses Ereignis nur einmal im Seitenlebenszyklus ausgelöst, wenn das Dokument vollständig von den Browsern geladen wurde. Um bestimmte Elemente zu beobachten, müssen Sie diesen Elementen Listener zum Ändern hinzufügen.

0
Pereira 4 Dez. 2013 im 17:15

Die Sache ist, dass der Browser nichts mehr ausführt, wenn Javascript ausgeführt wird. Das heißt, wenn Sie ein Div mit der ID "Beispiel" hinzufügen, können Sie nicht im selben Ereignis darauf zugreifen, in dem Sie es hinzugefügt haben.
Es gibt jedoch (meiner Meinung nach) eine saubere Problemumgehung dafür:

Führen Sie den Teil des Codes aus, der über
window.setTimout(func, 0); auf den dynamisch erstellten Inhalt zugreift.

Auf diese Weise kann der Browser andere Aufgaben ausführen (z. B. Rendern, Dom-Bearbeitung usw.) und Ihren Code ausführen, der darauf zugreift, sobald der Browser seine Arbeitswarteschlange beendet hat.

0
RononDex 6 Dez. 2013 im 17:35