Che cosa succede se abbiamo manipolare il DOM in requestAnimationFrame?

0

Domanda

La mia comprensione è ogni volta che c'è qualche DOM manipolazione come l'inserimento di un elemento DOM innescherebbe un reflow e probabilmente seguita da un ridisegno. Per favore mi corregga se sbaglio. Citando il MDN Web Docs,

La finestra.requestAnimationFrame() metodo indica al browser che si desidera eseguire un'animazione e richiede che il browser chiama una specifica funzione per l'aggiornamento di un'animazione prima del prossimo riverniciare

il requestAnimationFrame (un.k.un. aAF) callback viene chiamata appena prima che il browser è in procinto di aggiornare. Quindi, questo significa che se noi in qualche modo riesci a fare una DOM manipolazione all'interno di questo rAF (edit: e anche la coda di un altro rAF alla fine) che innesca un riflusso ogni volta, e quindi un ridisegno, si sarebbe bloccato in un ciclo infinito senza rendering in realtà nulla sullo schermo.

O è il caso che una volta che il browser ha deciso di fare un repaint, si bastone con esso e applicare tutti gli aggiornamenti che è successo nella RAF richiamata nel prossimo riverniciare?

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

Migliore risposta

1

ogni volta che c'è qualche DOM manipolazione come l'inserimento di un elemento DOM innescherebbe un reflow e probabilmente seguita da un ridisegno

La pittura d'azione viene eseguita in modo asincrono, in modo da "trigger" deve essere intesa in questo modo. Prima il codice JavaScript finirà prima che realmente accade.

se abbiamo in qualche modo riesci a fare una DOM manipolazione all'interno di questo rAF (edit: e anche la coda di un altro rAF alla fine) che innesca un riflusso ogni volta, e quindi un ridisegno, si sarebbe bloccato in un ciclo infinito senza rendering in realtà nulla sullo schermo.

La necessità di ridisegno accumulano e non sono soddisfatte in modo sincrono. Prima il codice è completo fino a quando la chiamata pila è vuota. Quindi non c'è nessun ciclo infinito qui.

O è il caso che una volta che il browser ha deciso di fare un repaint, si bastone con esso e applicare tutti gli aggiornamenti che è successo nella RAF richiamata nel prossimo riverniciare?

Sì. Quando la RAF callback viene chiamata, che il codice viene un'ultima possibilità per fare gli aggiornamenti del DOM, che possono accumulare ulteriori esigenze per la pittura. Se nella richiamata registrare anche un altro callback su RAF, non eseguirà in quel momento, ma in seguito: alla prossima volta che il browser preparerà il proprio riverniciare compito-così non quella attuale.

Esempio semplificato

Diciamo che hanno questo codice:

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

Quando si esegue, si ottiene la seguente sequenza:

  1. update è registrato come callback
  2. Lo sfondo modificare le pianificazioni un bisogno di riverniciatura
  3. Lo stack di chiamate diventa vuota
  4. Il browser inizia a ridipingere di lavoro, ma che tiene conto non c'è un marchio registrato di callback. Così si rimuove questa registrazione (perché si deve eseguire solo una volta) e lo esegue update prima di fare qualsiasi cosa.
  5. La larghezza di modificare le pianificazioni un bisogno di riverniciatura. L'elenco dei cambiamenti di ora include lo sfondo cambia e questo cambio di larghezza e qualsiasi effetto a cascata che è stato calcolato. (Come viene rappresentato è dipendente dal browser)
  6. Il update la funzione è registrato come richiamata di nuovo.
  7. Il browser controlla ora cosa si deve fare come parte di questo repaint di lavoro, ed esegue tutto ciò che è necessario per visualizzare gli effetti di sfondo e le variazioni di larghezza.
  8. Il lavoro di vernice estremità. Tutto ciò che è a sinistra è registrato update richiamata.
  9. Quando il browser esegue la successiva verniciatura, si ricomincia dal punto 4, ma ora non c'è in coda di sfondo cambia più. Per il resto sarà la stessa del processo.
2021-11-21 12:57:10

"4. Il browser inizia il suo layout/ridipingere lavoro," e ' abbastanza complicato, formulazione, penso che dire "il browser viene avviato l'aggiornamento del rendering" sarebbe un po ' meno confusione. Il layout e il ridisegno sono separati, si può benissimo forza di un layout in modo sincrono da utente-codice catastale, non è possibile forzare un repaint, che sarà sempre l'ultimo passaggio di rendering passi. Inoltre, mi sento le risposte ai primi punti sarebbe molto più semplice da ricordare dal get-go che raf(()=>raf(fn2)) pianifica fn2 a fuoco il prossimo frame. Altrimenti questa risposta è corretta.
Kaiido

@Kaiido, grazie per il tuo commento. "si può benissimo forza di un layout in modo sincrono da utente-codice catastale": si intende un utente percepibile cambiamento nel layout? si può dare un codice di esempio?
trincot

Qualche modo, ho rimosso il riferimento al layout.
trincot

gist.github.com/paulirish/5d52fb081b3570c81e3a Ecco un elenco di ciò che innesca il layout, e sì, è "user-percepibile": stackoverflow.com/questions/55134528/...
Kaiido

Va Bene, Kaiido!
trincot

In altre lingue

Questa pagina è in altre lingue

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