Ce se întâmplă dacă ne manipula DOM în requestAnimationFrame?

0

Problema

Înțelegerea mea este ori de câte ori este unii DOM manipulare cum ar fi introducerea unui element de DOM-ar declanșa un reflow si cel mai probabil urmat de o vopsi. Vă rugăm să corectați-mă dacă greșesc. Cu referire la MDN Web Docs,

La fereastră.requestAnimationFrame() metodă spune browser-ul pe care doriți să efectuați o animație și cererile pe care browser-ul solicită o anumită funcție pentru a actualiza o animație înainte de următoarea vopsi

la requestAnimationFrame (un.k.o. aAF) callback este apelată înainte de browser-ul este pe cale de a vopsi din nou. Deci, asta înseamnă că dacă am reuși cumva să facă o manipulare DOM în interiorul acestui rAF (edit: și, de asemenea, o altă coadă rAF la sfârșitul anului) care declanșează un reflow de fiecare dată și, astfel, o vopsi din nou, ne-ar fi blocat într-o buclă fără a face de fapt nimic pe ecran.

Sau este cazul în care odată ce browser-ul a decis să facă o vopsi, se va lipi cu ea și se aplică toate actualizările care s-a întâmplat în RAF de apel invers, în următorii vopsi?

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

Cel mai bun răspuns

1

ori de câte ori este unii DOM manipulare cum ar fi introducerea unui element de DOM-ar declanșa un reflow si cel mai probabil urmat de un vopsi

Pictura acțiune are loc în mod asincron, astfel încât "trigger" ar trebui să fie înțeleasă în acest fel. Primul cod JavaScript va termina înainte să se întâmple asta.

dacă am reuși cumva să facă o manipulare DOM în interiorul acestui rAF (edit: și, de asemenea, o altă coadă rAF la sfârșitul anului) care declanșează un reflow de fiecare dată și, astfel, o vopsi din nou, ne-ar fi blocat într-o buclă fără a face de fapt nimic pe ecran.

Care are nevoie pentru a vopsi din nou se acumulează și nu sunt sincron îndeplinite. În primul rând codul dvs. trebuie să completeze, până la apel stiva este goală. Deci, nu există nici o buclă infinită aici.

Sau este cazul în care odată ce browser-ul a decis să facă o vopsi, se va lipi cu ea și se aplică toate actualizările care s-a întâmplat în RAF de apel invers, în următorii vopsi?

Da. Când RAF de apel invers este numit, codul devine o ultimă șansă de a face update la DOM, care se pot acumula în continuare nevoie pentru pictura. În cazul în care callback vă înregistra, de asemenea, un alt apel invers pe RAF, acesta nu va executa la acel moment, dar mai târziu: la următoarea dată că browser-ul va pregăti vopsi sarcina ... deci nu cel actual.

Exemplu simplificat

Să presupunem că aveți acest cod:

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);
}

Când se execută, vom obține următoarea secvență:

  1. update este înregistrat ca callback
  2. Schimbarea de fond programe nevoie de revopsire
  3. La callstack devine gol
  4. Browser-ul începe sa vopsi din nou loc de muncă, dar ia în considerare nu este înregistrat de apel invers. Deci se elimină această înregistrare (pentru că ar trebui să rula doar o singură dată) și execută update înainte de a face orice altceva.
  5. Lățimea schimba programele nevoie de revopsire. Lista de modificări include acum schimbarea de fond și această schimbare latime si orice efect de cascadă, care a fost calculat. (Cum este reprezentată este browser-dependente)
  6. La update funcția este înregistrată drept de apel invers din nou.
  7. Browser-ul verifică acum ce trebuie să facă, ca parte a acestui vopsi din nou loc de muncă, și de a efectua tot ceea ce este necesar pentru a vizualiza efectele de fundal și lățimea modificări.
  8. Vopsea de locuri de muncă se încheie. Tot ce rămâne este înregistrat update apel invers.
  9. Atunci când browser-ul îndeplinește următoarele vopsea ciclu, vom începe din nou de la pasul 4, dar acum nu există nici un fundal în coadă-de a schimba orice mai mult. Pentru restul va fi același proces.
2021-11-21 12:57:10

"4. Browser-ul începe sa layout/vopsi din nou de treabă", care e destul de confuz formulare, cred că a spune "browser-ul începe actualizarea rendering" ar fi un pic mai puțin confuz. Dispunerea și vopsi din nou sunt separate, puteți foarte bine vigoare un aspect sincron de la utilizator-codul funciar, nu poți forța o vopsi, care va fi întotdeauna ultimul pas de redare pași. De asemenea, mă simt răspunsurile la primele puncte ar fi mult mai simplu, amintindu-de la get-du-te, că raf(()=>raf(fn2)) va programa fn2 la foc la următorul cadru. În caz contrar, acest răspuns este corect.
Kaiido

@Kaiido, multumesc pentru comentariu. "ai putea foarte bine vigoare un aspect sincron de la utilizator-codul funciar": adică un utilizator-schimbare perceptibilă în layout? poti da un exemplu de cod din asta?
trincot

Nici un fel, am scos de referință pentru layout.
trincot

gist.github.com/paulirish/5d52fb081b3570c81e3a Aici este o listă de ceea ce declanseaza layout, și da, e mai "user-perceptibilă": stackoverflow.com/questions/55134528/...
Kaiido

Bine, Kaiido!
trincot

În alte limbi

Această pagină este în alte limbi

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