Die Komplexität von unendlichem Scrollen

Zusammenfassung: Verwenden Sie Ihre DOM-Elemente wieder und entfernen Sie diejenigen, die weit vom Darstellungsbereich. Verwenden Sie Platzhalter, um verzögerte Daten zu berücksichtigen. Hier ist ein demo und den Code für die unendliche Version Scroller.

Überall im Internet gibt es unendliche Scroller. Die Künstlerliste von Google Music ist die Timeline von Facebook und der Livefeed von Twitter. Ich Scrollen Sie nach unten, bevor Sie das Ende erreichen, werden wie von Zauberhand neue Inhalte scheinbar aus dem Nichts. Es ist eine nahtlose Erfahrung für die Nutzenden und es ist einfach, sehen Sie sich den Einspruch an.

Die technische Herausforderung hinter einem unendlichen Scroller ist jedoch schwieriger als erscheint. Die Bandbreite der Probleme, auf die Sie stoßen, wenn Sie „The Right ThingTM“ durchführen möchten ist riesig. Es beginnt mit einfachen Dingen wie den Links in der Fußzeile, die praktisch unerreichbar, da die Fußzeile immer wieder weggeschoben wird. Die immer schwieriger werden. Wie gehen Sie mit einem Ereignis zur Größenanpassung um, wenn jemand sein vom Hoch- ins Querformat wechseln, oder wie verhindert man, schmerzhaft angehalten werden, wenn die Liste zu lang wird?

The right whatTM

Wir dachten, das ist ausreichend, um eine Referenzimplementierung zu entwickeln. die Ihnen zeigt, wie Sie diese Probleme wiederverwendbar angehen und gleichzeitig Leistungsstandards einhalten.

Wir wenden drei Techniken an, um unser Ziel zu erreichen: DOM-Recycling, Tombstones und Scroll-Anker.

Unser Demo-Fall ist ein Hangouts-ähnliches Chatfenster, in dem wir über die Nachrichten kommunizieren. Als Erstes brauchen wir eine unendliche Quelle für Chats. Nachrichten. Technisch gesehen gibt es tatsächlich unendlich, aber aufgrund der Menge an Daten, die zur Verfügung steht, die sie auch sein könnten. Der Einfachheit halber codieren wir einfach Gruppe von Chat-Nachrichten und Auswahl der Nachricht, des Autors und gelegentlicher Bildanhänge unter mit ein wenig künstlicher Verzögerung, um sich etwas ähnlich wie die echtes Netzwerk.

Screenshot der Chat-App

DOM-Recycling

Das DOM-Recycling ist eine nicht ausgelastete Technik, um die Anzahl der DOM-Knoten niedrig zu halten. Die Generell gilt es, bereits erstellte DOM-Elemente zu verwenden, die nicht auf dem Bildschirm zu sehen sind. zu erstellen. DOM-Knoten selbst sind zwar günstig, nicht kostenlos, da jede von ihnen zusätzliche Kosten für Speicher, Layout, Stil und Farbe verursacht. Low-End-Geräte werden merklich langsamer, wenn sie nicht völlig unbrauchbar sind, Website hat ein zu großes DOM, um sie zu verwalten. Denken Sie auch daran, dass jede Layoutänderung und Neuanwendung Ihrer Stile – ein Prozess, der jedes Mal ausgelöst wird, wenn eine Klasse zu einem Knoten hinzugefügt oder daraus entfernt werden – wächst mit einem größeren DOM kostspieliger. Durch das Recyceln der DOM-Knoten wird die Gesamtzahl der erheblich niedriger, wodurch all diese Prozesse schneller werden.

Die erste Hürde ist das Scrollen selbst. Da wir nur eine kleine Teilmenge davon haben, im DOM verfügbar sind, müssen wir eine andere Methode finden, damit die Bildlaufleiste des Browsers theoretisch nicht. Wir verwenden ein 1 x 1 Pixel großes Sentinel-Element mit einer Transformation um zu erzwingen, dass das Element, das die Elemente enthält, also die Startbahn, Höhe. Wir platzieren jedes Element auf dem Laufsteg auf einer eigenen Ebene, dass die Schicht der Start- und Landebahn komplett leer ist. Keine Hintergrundfarbe, nichts. Wenn die Ebene des Laufstes nicht leer ist, kommt sie nicht für die Browserebene infrage. und wir müssen eine Textur auf unserer Grafikkarte speichern, Höhe von ein paar hunderttausend Pixeln. Definitiv nicht praktikabel für Mobilgerät.

Beim Scrollen prüfen wir, ob sich der Darstellungsbereich dem bis zum Ende der Start- und Landebahn. In diesem Fall verlängern wir die Start- und Landebahn, indem wir die Sentinel- und verschieben die Elemente, die den Darstellungsbereich verlassen haben, an das Ende des und sie mit neuen Inhalten füllen.

<ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder"></ph> Startbahn Sentinel Darstellungsbereich

Dasselbe gilt für das Scrollen in die andere Richtung. Wir werden jedoch niemals Verkleinern Sie die Start- und Landebahn, damit die Position der Bildlaufleiste einheitlich sind.

Grabsteine

Wie bereits erwähnt, versuchen wir, das Verhalten unserer Datenquelle in der realen Welt. Mit Netzwerklatenz und allem. Wenn unsere die Nutzende nutzen, um schnell am letzten Element vorbeizuscrollen. für die wir Daten haben. In diesem Fall platzieren wir ein Tombstone-Element – Platzhalter – der durch den Artikel ersetzt wird, sobald der Daten sind da. Grabsteine werden ebenfalls recycelt und haben einen separaten Pool DOM-Elemente wiederverwendbar sind. Das ist wichtig, damit wir einen netten Übergang von einer zu dem mit Inhalten gefüllten Element hinzu. Dies wäre ansonsten und die Nutzenden verwirren, sodass sie den Überblick verlieren, auf die Sie sich konzentrieren sollten.

Ein solches
Grabstätte. Sehr steinern. Wow.

Eine interessante Herausforderung besteht darin, dass reale Objekte eine größere Höhe haben können des Tombstone-Elements aufgrund der unterschiedlichen Textmenge pro Artikel oder eines beigefügten Bild. Um dieses Problem zu beheben, passen wir die aktuelle Scrollposition jedes Mal an. Daten eingehen und ein Tombstone oberhalb des Darstellungsbereichs ersetzt wird. Verankerung der Scrollposition zu einem Element statt zu einem Pixelwert. Dieses Konzept ist als Scroll-Anker.

Scroll-Anker

Unsere Scroll-Verankerung wird aufgerufen, wenn Tombstones und wann die Fenstergröße angepasst wird (dies geschieht auch, wenn das Gerät umgedreht wird!). Wir müssen herausfinden, welches Element der Darstellungsbereich ist. Da dieses Element nur teilweise sichtbar ist, Versatz vom oberen Rand des Elements speichern, wo der Darstellungsbereich beginnt.

Ankerdiagramm scrollen.

Wenn die Größe des Darstellungsbereichs angepasst wird und es Änderungen an der Start- und Landebahn gibt, können wir die für die Nutzenden optisch identisch erscheint. Gewonnen! Mit Ausnahme von dass sich die Höhe jedes Elements möglicherweise geändert hat. wie weit unten der verankerte Content platziert werden soll? Das tun wir nicht! Um es herauszufinden, müssten wir jedes Element über dem verankerten Element anordnen und alle ihre Höhen und Tiefen, könnte dies nach einer Größenänderung zu einer längeren Pause führen. das wollen. Stattdessen gehen wir davon aus, dass alle obigen Artikel die gleiche Größe haben. und die Scrollposition entsprechend anpassen. Da Elemente auf die Startbahn gescrollt haben, passen wir die Scroll-Position an, das Layout bis zum tatsächlichen Bedarf anpassen.

Layout

Dabei habe ich ein wichtiges Detail übersprungen: das Layout. Jedes Recycling eines DOM-Elements Layout der gesamten Start- und Landebahn neu gestalten, sodass wir 60 Bilder pro Sekunde erreicht. Um dies zu vermeiden, auf uns selbst zu übertragen und absolut positionierte Elemente mit Transformationen zu verwenden. Auf diese Weise können wir so tun, als wären alle Elemente weiter oben auf der Startbahn wenn in Wirklichkeit nur freier Platz vorhanden ist. Da wir die Positionen, an denen jedes Element landet, das richtige Element sofort aus dem Cache zu laden, wenn die Nutzenden zurückscrollen.

Im Idealfall werden Elemente nur einmal neu gezeichnet, wenn sie an das DOM angehängt werden. und vom Hinzufügung oder Entfernen anderer Elemente auf dem Laufsteg unbeeindruckt bleiben. Das bedeutet, aber nur mit modernen Browsern.

Neueste Änderungen

Seit Kurzem unterstützt Chrome CSS-Begrenzungen, eine Funktion mit der wir dem Browser mitteilen können, dass ein Element eine Grenze Layout und Farbgestaltung. Da wir das Layout hier selbst erstellen, ist es Anwendung der Begrenzung. Wenn wir dem Laufsteg ein Element hinzufügen, wissen wir, die anderen Elemente müssen nicht von der Layoutänderung betroffen sein. Jedes Element sollte contain: layout erhalten. Auch der Rest unserer Website soll nicht beeinträchtigt werden. Daher sollte auch die Laufbahn diese Stilanweisung erhalten.

Außerdem haben wir darüber nachgedacht, IntersectionObservers als Mechanismus, um zu erkennen, Die Nutzenden sind weit genug gescrollt, sodass wir mit dem Recycling von Elementen beginnen und neue Daten. Für IntersectionObservers wird jedoch eine hohe Latenz festgelegt, mit requestIdleCallback). Daher fühlen wir uns möglicherweise weniger gut IntersectionObservers als ohne. Sogar bei unserer aktuellen Implementierung mit dem Dieses Problem tritt beim scroll-Ereignis auf, da Scroll-Ereignisse bei einem auf einer "Best-Effort-Basis" basieren. Houdini’s Compositor Worklet ist die High-Fidelity-Lösung für dieses Problem.

Immer noch nicht perfekt

Unsere aktuelle Implementierung des DOM-Recycling ist nicht ideal, da dabei alle Elemente hinzugefügt werden. durch den Darstellungsbereich durchlaufen, anstatt sich nur um die auf dem Bildschirm. Wenn du also wirklich schnell scrollst, siehst du so viel Arbeit für Layout und Farbe in Chrome, dass es nicht mehr mithalten kann. Sie beenden nur den Hintergrund zu sehen. Es ist nicht das Ende der Welt, auf jeden Fall verbessert werden.

Wir hoffen, dass Sie sehen, wie schwierig eine gute User Experience mit hohen Leistungsstandards kombinieren. Mit Progressive Web-Apps werden zu den Kernfunktionen auf Mobiltelefonen, immer wichtiger werden und Webentwickler müssen weiter in mit Mustern, die Leistungsbeschränkungen berücksichtigen.

Den gesamten Code finden Sie in unserem Repository. Wir haben dass sie wiederverwendbar bleiben, aber nicht als Bibliothek npm oder als separates Repository. Der Hauptzweck dient dem Bildungsbereich.