Złożoność nieskończonego przewijania

TL;DR: ponownie wykorzystaj elementy DOM i usuń te, które są oddalone widoczny obszar. Aby uwzględnić dane opóźnione, użyj zmiennych. Oto demo i kod funkcji nieskończonej przewijanie.

W całym internecie pojawiają się przewijające treści bez końca. Lista wykonawców w Muzyce Google to po pierwsze, oś czasu na Facebooku jest jedną z nich, podobnie jak kanał na żywo na Twitterze. Ty przewiń w dół, zanim dotrzesz na sam dół, automatycznie pojawią się nowe treści. pozornie nie znikąd. To wygodne dla użytkowników rozwiązanie, zapoznać się z odwołaniem.

Jednak wyzwanie techniczne z nieskończonym przewijaniem jest trudniejsze. . Zakres problemów, które pojawiają się, gdy chcesz wykonać The Right ThingTM jest ogromna. Zaczyna się od prostych rzeczy, np. linków w stopce zmienia się jest praktycznie nieosiągalna, ponieważ treść odciąga stopkę od strony. Ale i że problemy stają się trudniejsze. Co zrobić w przypadku zmiany rozmiaru, gdy ktoś zmieni telefonu z pionowej na poziomą lub jak zapobiegać tarciu telefonu. gdy lista staje się zbyt długa?

Właściwa rzeczTM

Uznaliśmy, że to wystarczający powód, by opracować referencyjną implementację który pokazuje, jak rozwiązywać wszystkie te problemy w sposób wielokrotnego użytku, i utrzymanie standardów wydajności.

Aby osiągnąć nasz cel, użyjemy 3 technik: recyklingu DOM, elementów tombstone i zakotwiczenia przewijania.

Przykładem może być okno czatu przypominające Hangouts, przez wiadomości. Pierwszą rzeczą, jakiej potrzebujemy, jest nieskończone źródło czatów wiadomości. Technicznie rzecz biorąc, żaden użytkownik nie ma takiego nieskończonego przewijania naprawdę ale przy dużej ilości danych, które można w niej umieścić. być może. Dla uproszczenia zakodujemy na stałe zestaw wiadomości na czacie, w tym wiadomości, autora oraz okazjonalnie załączony obraz z drobnym opóźnieniem, aby zachowywać się trochę bardziej jak prawdziwą sieć.

Zrzut ekranu aplikacji Google Chat

Recykling DOM

Recykling DOM to rzadko używana technika utrzymywania niskiej liczby węzłów DOM. ogólną koncepcją jest używanie już utworzonych elementów DOM, które są poza ekranem. tworzenia nowych. Oczywiście węzły DOM są tanie, nie są bezpłatne, ponieważ każdy z nich wiąże się z dodatkowymi kosztami pamięci, układu, stylu i malowania. Urządzenia niskiej jakości są znacznie wolniejsze, jeśli nie są całkowicie bezużyteczne, jeśli ma zbyt duży DOM, aby nim zarządzać. Pamiętaj też, że każdy przekaźnik i ponownego zastosowania stylów – procesu wywoływanego za każdym razem, gdy klasa jest dodawana do węzła lub z niego usunięta – rośnie droższy wraz z większym DOM. Recykling węzłów DOM oznacza, że zachowamy łączną liczbę znacznie niższe, co przyspiesza wszystkie te procesy.

Pierwsza przeszkoda to samo przewijanie. Mamy tylko niewielki podzbiór, dostępnych w danym momencie elementów DOM, musimy znaleźć inny sposób aby pasek przewijania w przeglądarce prawidłowo odzwierciedlał ilość treści teoretycznie. Wykorzystamy element Seninel o wymiarach 1 na 1 piksel z przekształceniem dzięki któremu element, który zawiera przedmioty (pas startowy), wysokość. Będziemy promować każdy element na wybiegu na własną warstwę, że warstwa pasa startowego jest całkowicie pusta. Brak koloru tła, nic. Jeśli warstwa na pasie startowym nie jest pusta, nie może być wyświetlana przez i musimy zapisać teksturę na karcie graficznej, Mają wysokość kilkaset tysięcy pikseli. Na pewno nie urządzenia mobilnego.

Podczas przewijania sprawdzamy, czy widoczny obszar jest wystarczająco blisko na samym końcu pasa startowego. Jeśli tak, wydłużymy pas startowy, przesuwając i przeniesienie elementów, które opuściły widoczny obszar, na dół i zapełniać je nowymi treściami.

Wybieg Sentinel Widok

To samo dotyczy przewijania w przeciwnym kierunku. Nigdy jednak nie będziemy w naszym wdrożeniu można zmniejszyć pas startowy, tak by pozycja paska przewijania nie zmieniała się spójne.

Elementy tombstone

Jak już wspomnieliśmy, staramy się, aby nasze źródło danych zachowało się jak w prawdziwym świecie. Z opóźnieniami w sieci i innymi funkcjami. Oznacza to, że jeśli Szybkie przewijanie pozwala szybko pominąć ostatni element. dla których mamy dane. W takim przypadku umieścimy nagrobek placeholder – element zostanie zastąpiony faktyczną treścią, dane dostarczono. Elementy tombstone są również poddawane recyklingowi i znajdują się w osobnym basenie wielokrotnego użytku z elementami DOM. Potrzebujemy go, żeby ułatwić sobie przejście złożony z przedmiotów układ, który w innym przypadku byłby bardzo nie są dla użytkownika przydatne i mogą sprawić, że straci on świadomość na których będziemy się skupić.

Taka
grób. Bardzo kamienia. Niesamowite.

Prawdziwe przedmioty mogą mieć większą wysokość niż z powodu różnicy ilości tekstu w poszczególnych elementach lub w załączniku . Aby rozwiązać ten problem, będziemy za każdym razem dostosowywać bieżącą pozycję przewijania na podstawie przesłanych danych i zastępowany jest element graficzny nad widocznym obszarem, zakotwiczony pozycję przewijania do elementu, a nie do wartości w pikselach. Ta koncepcja nazywane zakotwiczeniem przewijania.

Zakotwiczenie przewijania

Nasze zakotwiczenie przewijania będzie wywoływane zarówno przy zastępowaniu elementów tombstone, czyli a także gdy zmienia się rozmiar okna (także wtedy, gdy urządzenie odwracanie się!). Musimy określić, który element jest najwyżej widoczny czyli widoczny obszar. Ten element może być tylko częściowo widoczny, dlatego też zapisuje odsunięcie od górnej części elementu, w którym zaczyna się widoczny obszar.

Przewiń diagram zakotwiczenia.

Jeśli zmieni się rozmiar widocznego obszaru, a na pasie startowym nastąpiły zmiany, możemy przywrócić które są wizualnie identyczne z punktu widzenia użytkownika. Wygrana! Z wyjątkiem zmiany rozmiaru co oznacza, że każdy element mógł zmienić swoją wysokość. Jak więc i jak daleko powinny znajdować się treści zakotwiczone. Nie mamy! Aby sprawdzić musielibyśmy umieścić każdy element nad zakotwiczonym elementem i dodać wszystkie ich wysokości; może to spowodować znaczne wstrzymanie po zmianie rozmiaru. tego potrzebujesz. Zamiast tego przyjmujemy, że każdy z powyższych elementów ma taki sam rozmiar. jako nagrobek i odpowiednio dostosować pozycję przewijania. Ponieważ elementy są przewinięcie do pasa startowego, dostosowujemy pozycję przewijania, co pozwala opóźnić w czasie, gdy będzie potrzebny.

Układ

Pominięto ważny szczegół: układ. Każdy recykling elementu DOM przepuszczaliby cały pas startowy, co dałoby nam dużo niższego docelowa wartość to 60 klatek na sekundę. Aby tego uniknąć, bierzemy na siebie ciężar na układają się wokół siebie i używamy bezwzględnie rozmieszczonych elementów z przekształceniami. Dzięki temu możemy udawać, że wszystkie elementy dalej na wybiegu są nieruchome. które zajmują przestrzeń, a w rzeczywistości jest tylko pusta przestrzeń. Ponieważ możemy też buforować lokalizacje, na których znajduje się każdy element, natychmiast wczytuje odpowiedni element z pamięci podręcznej, gdy użytkownik przewinie stronę do tyłu.

W idealnej sytuacji elementy byłyby malowane tylko raz po przyłączeniu do DOM. dodawania i usuwania innych przedmiotów na wybiegu – nie szkodzi. To jest ale tylko w nowoczesnych przeglądarkach.

Najnowsze zmiany

Niedawno Chrome obsługuje funkcję przechowywania CSS który pozwala nam określić, że element jest granicą dla przeglądarki. układ i malowanie. Sami tworzymy układ strony, wniosku o ujawnienie informacji. Za każdym razem, gdy dodajemy element na pasie startowym, wiemy przekaz nie musi wpływać na inne elementy. Każdy element powinien uzyskać contain: layout. Nie chcemy też mieć wpływu na resztę naszej witryny, więc sama pasa startowa również powinna otrzymać tę dyrektywę dotyczącą stylu.

Rozważyliśmy też używanie IntersectionObservers jako mechanizm wykrywający, kiedy użytkownik przewinął stronę na tyle daleko, że mogliśmy zacząć recykling elementów i wczytać nowe. i skalowalnych danych. Parametry IntersectionObservers są jednak określone jako duże opóźnienia (jak w sytuacji, używając requestIdleCallback), więc możemy odczuć mniejszą reagowanie na IntersectionObservers. Nawet nasza obecna implementacja za pomocą Ten problem występuje w zdarzeniu scroll, ponieważ zdarzenia przewijania są wysyłane w ramach najlepszych starań. W ostatecznym rozrachunku Worklet Houdini’s Compositor najbardziej precyzyjne rozwiązanie tego problemu.

Nadal nie jest doskonały

Obecna implementacja recyklingu DOM nie jest idealna, ponieważ dodaje wszystkie elementy które przechodzą przez widoczny obszar, a nie tylko na ekranie. Oznacza to, że podczas prawdziwego przewijania tyle pracy nad układami i malowaniem w Chrome, że nie jest w stanie za nią nadążyć. Zakończysz nie widząc nic poza tłem. To nie koniec świata, zdecydowanie trzeba coś ulepszyć.

Mamy nadzieję, że przekonasz się, jak trudne mogą być proste problemy, gdy chcesz łączą wygodę użytkowników z wysokimi standardami wydajności. Na Progresywne aplikacje internetowe staną się podstawowym elementem na telefonach komórkowych, staje się coraz ważniejsza i programiści stron internetowych będą musieli w dalszym ciągu inwestować z wykorzystaniem wzorców uwzględniających ograniczenia wydajności.

Cały kod można znaleźć w naszym repozytorium. Gotowe ale nie będziemy udostępniać jej jako rzeczywistej biblioteki. npm lub jako oddzielne repozytorium. Głównym zastosowaniem jest edukacja.