DocumentFragment: Was ist das und wie kann man es (nicht) bekämpfen?

Haftungsausschluss
Es scheint, als würde ich eine neue Artikelserie starten - ein wenig langweilig und rein zweckmäßig. Sie erklären die Punkte, die meinen Schülern oft Schwierigkeiten bereiten. Wenn Sie ein erfahrener Webentwickler sind, werden Sie höchstwahrscheinlich nicht interessiert sein. Wenn Sie auf Perversionen in der Macht von JS am Freitag warten, werden sie leider nicht hier sein.


Eines der Dinge, die Schüler regelmäßig nicht verstehen können, ist DocumentFragment. Im Allgemeinen kann ich ihnen keine Vorwürfe machen. Mit äußerer Einfachheit hat es mehrere nicht offensichtliche und sogar nicht intuitive Eigenschaften. In diesem Artikel möchte ich alles sammeln, was ein Anfänger über ihn wissen muss.

Bild

Was ist das


Ein DocumentFragment ist ein Container, der eine beliebige Anzahl von DOM-Elementen enthalten kann. Wenn ganz einfach, können Sie es sich als einen Eimer vorstellen. Darin sind Elemente gestapelt, so dass sie im richtigen Moment sofort entsorgt werden können.

Wie erstelle ich?


Grundstufe.

var fragment = document.createDocumentFragment(); 

Es gibt auch andere Möglichkeiten, aber darüber unten.

Warum brauche ich


Wie ich oben geschrieben habe, um DOM-Elemente zu speichern. "Aber sie können in einer gewöhnlichen Diva gespeichert werden", kann der Leser Einwände erheben. Das Fragment hat jedoch eine einzigartige Eigenschaft, die es zum besten Kandidaten für diese Rolle macht. Betrachten Sie den folgenden Code:

 var fragment = document.createDocumentFragment(); var parentDiv = document.createElement("div"); var div1 = document.createElement("div"); var div2 = document.createElement("div"); fragment.appendChild(div1); fragment.appendChild(div2); //   parentDiv.appendChild(fragment); console.log(parentDiv.children); 

Was sagt uns die Konsole? Eine Person, die mit DocumentFragment nicht vertraut ist, könnte denken, dass parentDiv ein parentDiv fragment . Tatsächlich wird es aber zwei Kinder haben - div1 und div2 . Tatsache ist, dass das Fragment selbst kein DOM-Element ist, sondern nur ein Container für DOM-Elemente. Und wenn es als Argument an Methoden wie appendChild oder insertBefore , wird es nicht in den DOM-Baum eingebettet, sondern bettet dort seinen Inhalt ein.

Aber warum brauchst du es?


Die Eigenschaft "Eimer" ist natürlich gut, aber wie ist dies in der Praxis nützlich? DocumentFragment hat zwei Hauptanwendungsbereiche.

1. Speichern von HTML-Teilen, die keinen gemeinsamen Vorfahren haben.

Es gibt Situationen, in denen wir den Inhalt eines Elements ersetzen müssen, aber das Element selbst nicht berühren müssen. Angenommen, wir verwenden die Ereignisdelegierung und alle Ereignishandler, die für interne Elemente auftreten, werden an ein externes Div gehängt. In diesem Fall ist DocumentFragment ideal für uns:

 div.innerHTML = ""; div.appendChild(fragmentWithAllContent); 

"Aber können wir dem div sofort Elemente hinzufügen, wenn wir sie erstellen?" - Der ätzende Leser wird fragen. Wir können, aber es lohnt sich nicht, und deshalb.

2. Leistungsverbesserung bei mehreren Einsätzen.

Tatsache ist, dass der Browser jedes Mal, wenn wir etwas im aktiven DOM-Baum ändern, eine Reihe von Berechnungen durchführen muss. Hier können Sie zum Beispiel mehr darüber lesen. In diesem Artikel beschränken wir uns darauf zu erwähnen, dass es so einen schrecklichen Biest-Reflow gibt. Wenn wir der Seite ein Element hinzufügen, wacht dieses Biest auf und frisst ein Stück Prozessorzeit. Wenn wir nacheinander einhundert Elemente hinzufügen, wacht das Tier hundertmal auf und beißt hundertmal. Für den Benutzer kann dies bereits ein merkliches „Einfrieren“ sein.

Wenn wir dem DocumentFragment ein Element hinzufügen, führt dies nicht zu einem Reflow, da das Fragment nicht Teil des aktiven DOM-Baums ist (und im Grunde nicht sein kann). Und vor allem: Wenn wir den Inhalt eines Fragments mit appendChild oder anderen ähnlichen Methoden einfügen, wird der Reflow nur einmal aufgerufen , unabhängig davon, wie viele Elemente sich im Fragment befinden.

Aus Gründen der Klarheit habe ich einen einfachen Benchmark erstellt, damit der Leser den Unterschied persönlich erkennen kann.

Upd: Genosse Nuit sagte, dass meine Worte für modernes Chrome nicht mehr wahr sind. Der Reflow wird nicht früher als nötig ausgeführt, und dank dessen funktioniert der Code ohne DocumentFragment tatsächlich schneller , und bei anderen Browsern ist dies nicht so offensichtlich. Bevor Sie sich für die Verwendung von Fragmenten entscheiden, müssen Sie ein Profil erstellen und die Zielgruppe der Website untersuchen.

Nuancen


Es gibt zwei Funktionen, die es Anfängern oft schwer machen, Fragmente zu verwenden. Erstens: Wie ich oben geschrieben habe, ist ein Fragment kein DOM-Element . Dies bedeutet, dass es viele bekannte Methoden und Eigenschaften fehlt, insbesondere innerHTML . Daher können Sie eine Zeichenfolge nicht einfach in den Inhalt eines Fragments umwandeln. Wie das geht, ist nicht einfach, wird weiter unten beschrieben.

Das zweite Merkmal: das Fragment bei Verwendung von "Beute". Genauer gesagt wird es geleert. Wenn wir div.appendChild(fragment) , werden alle div.appendChild(fragment) des Fragments in ein div . Und da ein Element nicht mehr als ein übergeordnetes Element haben kann, bedeutet dies, dass sie aus dem Fragment entfernt werden! Um dieses Verhalten zu vermeiden, wenn es unerwünscht ist, können Sie cloneNode .

<template> -Tag


Es gibt einen Ort, an dem Sie auf DocumentFragment stoßen können, ohne es über JS zu erstellen. Dies ist die content des Vorlagenelements.

Das <template> speziell zum Speichern von HTML-Codeteilen entwickelt, jedoch nicht zum Laden des Browsers im Voraus. Was sich in diesem Tag befindet, wird nicht Teil des aktiven DOM-Baums. Insbesondere (Neulinge stoßen häufig auch darauf) können sie mit querySelector nicht gefunden werden. Aus HTML-Code im <template> -Tag erstellte Elemente werden nicht zu untergeordneten Elementen. Stattdessen kann JavaScript über die Eigenschaft content auf sie zugreifen, was eine Überraschung ist! - nur DocumentFragment.

Mit dem Vorlagenelement können Sie ein Fragment aus einer Zeichenfolge erstellen:

 function createFragmentFromString(str){ var template = document.createElement("template"); template.innerHTML = str; return template.content; } 

Nachwort


Wenn Sie neu in der Webentwicklung sind, hoffe ich, dass Sie viel gelernt haben. Wenn Sie ein erfahrener Entwickler sind, möchten Sie diesen Artikel möglicherweise durch etwas ergänzen. In diesem Fall zögern Sie nicht, in den Kommentaren darüber zu schreiben. Danke fürs Lesen und einen schönen Tag.

Source: https://habr.com/ru/post/de413287/


All Articles