Co się stanie, jeśli będziemy manipulować DOM w requestAnimationFrame?

0

Pytanie

Rozumiem, że za każdym razem, gdy wystąpi jakakolwiek manipulacja DOM, na przykład, wstawianie elementu DOM, spowoduje rysowane i najprawdopodobniej nastąpi powtórne malowanie. Proszę, poprawcie mnie, jeśli się mylę. Cytowanie dokumentów internetowych MDN,

Metoda window.requestAnimationFrame() informuje przeglądarkę, że chcesz wykonać animację, i żąda, aby przeglądarka wzywał określonej funkcji w celu aktualizacji animacji przed następnym odświeżania

oddzwanianie requestAnimationFrame (on sam aAF) jest wywoływana tuż przed tym, jak przeglądarka będzie przemalować. Czy to oznacza, że jeśli nam się w jakiś sposób uda się wykonać manipulację DOM wewnątrz tego rAF (edit: a także umieścić w kolejności innej rAF w końcu), który za każdym razem uruchamia rysowane i, w konsekwencji, rysowane, utkniemy w nieskończonej pętli, w rzeczywistości nic się nie wyświetla na ekranie.

Czy to przypadek, w którym, jak tylko przeglądarka postanowił zrobić odowieżenie, będzie trzymać się jej i zastosować wszelkie aktualizacje, które miały miejsce przy odwrotnym połączeniu RAF, przy następnej перекраске?

dom javascript reflow repaint
2021-11-21 07:17:28
1

Najlepsza odpowiedź

1

za każdym razem, gdy wystąpi jakakolwiek manipulacja DOM, takie jak wstawianie elementu DOM, spowoduje rysowane i, najprawdopodobniej, po niej nastąpi powtórne malowanie

Akcja rysowania odbywa się asynchronicznie, więc "wyzwalacz" należy rozumieć dokładnie tak. Najpierw twój kod JavaScript zakończy się do tego, jak to się dzieje w rzeczywistości.

jeśli nam się w jakiś sposób uda się wykonać manipulację DOM wewnątrz tego rAF (edit: a także umieścić w kolejności innej rAF w końcu), który za każdym razem uruchamia rysowane i, w konsekwencji, rysowane, utkniemy w nieskończonej pętli, w rzeczywistości nic się nie wyświetla na ekranie.

Potrzeby w перекраске gromadzą się i nie są spełnione synchronicznie. Najpierw twój kod powinien być zakończony, dopóki stos wywołań nie jest pusty. Tak, tu nie ma nieskończonej pętli.

Czy to przypadek, w którym, jak tylko przeglądarka postanowił zrobić odowieżenie, będzie trzymać się jej i zastosować wszelkie aktualizacje, które miały miejsce przy odwrotnym połączeniu RAF, przy następnej перекраске?

TAK. Kiedy wywoływana jest oddzwanianie RAF, ten kod dostaje ostatnią szansę dokonać aktualizacji w DOM, co może doprowadzić do dalszego gromadzenia potrzeb w malowaniu. Jeśli w tym odwrotnej wywołaniu można również zarejestrować inny oddzwanianie na RAF, z którym zostanie wykonany nie w tym czasie, a później: w następnym razem, gdy przeglądarka przygotuje swoje zadanie rysowania-tak, że nie aktualną.

Uproszczony przykład

Załóżmy, że masz ten kod:

requestAnimationFrame(update);

myElement.style.backgroundColor = "silver"; // This queues a need for repaint

function update() {
    // This queues a need for repaint
    myElement.style.width = Math.floor(Math.random() * 100) + "px";
    requestAnimationFrame(update);
}

Gdy to działa, otrzymujemy następującą sekwencję:

  1. update zarejestrowany jako callback
  2. Zmiana tła wskazuje na potrzebę malowanie
  3. Stos wywołań staje się pusty
  4. Przeglądarka zaczyna swoją pracę w перекраске, ale bierze pod uwagę, że jest zarejestrowany oddzwanianie. W ten sposób, że usuwa tę rejestrację (bo musi być wykonywane tylko jeden raz) i wykonuje update zanim zrobisz cokolwiek innego.
  5. Zmiana szerokości wskazuje na potrzebę malowanie. Lista zmian zawiera teraz zmiana tła i ta zmiana szerokości, a także każdy obliczony kaskadowy efekt. (To, jak to jest przedstawione, zależy od przeglądarki)
  6. To update funkcja ponownie zarejestruje się jak oddzwanianie.
  7. Teraz przeglądarka sprawdza, co ma zrobić w ramach tej pracy w перекраске, i wykonuje wszystkie niezbędne do wizualizacji efektów zmiany tła i szerokości.
  8. Praca z farbą kończy. Wszystko, co pozostało, jest zarejestrowany update oddzwonienie.
  9. Gdy przeglądarka wykona swój następny cykl rysowania, zaczniemy ponownie od kroku 4, ale teraz w kolejce nie ma już zmiany tła. Poza tym to będzie ten sam proces.
2021-11-21 12:57:10

"4. Przeglądarka zaczyna swoją pracę do składania/перерисовке", jest to dość skomplikowane sformułowanie, myślę, że powiedzieć "przeglądarka zaczyna aktualizować rendering" byłoby trochę mniej mylące. Układ i powtórne malowanie podzielone, można bardzo dobrze zmusić układ synchronicznie z kodem użytkownika, nie można wymusić przemalować, że zawsze będzie ostatnim krokiem na etapie renderowania. Poza tym, czuję, że odpowiedzi na pierwsze punkty były by o wiele łatwiej, gdyby od samego początku przypomniał, że raf(()=>raf(fn2)) będzie zaplanować fn2 aby strzelać w następnej klatki. W przeciwnym razie ta odpowiedź jest wierny.
Kaiido

@Kaiido, dziękuję za twój komentarz. "jesteś bardzo dobrze można zmusić układ synchronicznie z kodem użytkownika": masz na myśli postrzeganej przez użytkownika zmiany w układzie? czy możesz podać przykład kodu?
trincot

W każdym razie, usunąłem link na układ.
trincot

gist.github.com/paulirish/5d52fb081b3570c81e3a Oto lista tego, co uruchamia układ, i tak, to "jest postrzegana przez użytkownika": stackoverflow.com/questions/55134528/...
Kaiido

Dobrze, Кайидо!
trincot

W innych językach

Ta strona jest w innych językach

Русский
..................................................................................................................
Italiano
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................