O que acontece se nós manipular o DOM no requestAnimationFrame?

0

Pergunta

O meu entendimento é que sempre que há alguma manipulação do DOM, como a inserção de um elemento DOM provocaria um refluxo e, provavelmente, seguido por um redesenho. Por favor, corrija-me se estou errado. Citando o MDN Web Docs,

A janela.requestAnimationFrame() método que informa ao navegador que você deseja executar uma animação e pede que o navegador chama uma função especificada para atualizar uma animação antes da próxima redesenhar

o requestAnimationFrame (uma.k.um. aAF) de chamada de retorno é chamado antes de o navegador está para redesenhar. Então, isso quer dizer se nós, de alguma forma, conseguem fazer uma manipulação do DOM dentro deste rAF (edit: e também a fila de outro rAF no final), que provoca um refluxo de cada vez e, assim, um redesenho, nós estaria preso em um loop infinito sem realmente prestação de nada na tela.

Ou é o caso que, uma vez que o navegador tinha decidido fazer um redesenho, ele vai ficar com ela e aplique todas as atualizações que aconteceu na RAF de retorno no redesenho próximo?

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

Melhor resposta

1

sempre que há alguma manipulação do DOM, como a inserção de um elemento DOM provocaria um refluxo e, provavelmente, seguido por um redesenho

A pintura de ação ocorre de forma assíncrona, para "disparar" deve ser entendido dessa forma. O seu primeiro código JavaScript irá terminar antes que realmente acontece.

se nós, de alguma forma, conseguem fazer uma manipulação do DOM dentro deste rAF (edit: e também a fila de outro rAF no final), que provoca um refluxo de cada vez e, assim, um redesenho, nós estaria preso em um loop infinito sem realmente prestação de nada na tela.

As necessidades para redesenhar se acumulam e não são de forma síncrona cumprida. Primeiro, o seu código tem a completar até a chamada pilha está vazia. Portanto, não há loop infinito aqui.

Ou é o caso que, uma vez que o navegador tinha decidido fazer um redesenho, ele vai ficar com ela e aplique todas as atualizações que aconteceu na RAF de retorno no redesenho próximo?

Sim. Quando a RAF de retorno de chamada é chamada, o código fica uma última chance de fazer atualizações para o DOM, que pode acumular-se mais com as necessidades para a pintura. Se no retorno de chamada você também registrar outro chamada de retorno no RAF, ele não será executado no momento, mas mais tarde: na próxima vez que o navegador irá preparar a sua tarefa de redesenhar -- então não é a atual.

Exemplo simplificado

Vamos dizer que você tem esse código:

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 este executa, temos a seguinte seqüência:

  1. update é registado como de chamada de retorno
  2. O fundo de alteração de horários de uma necessidade de repintura
  3. A pilha de chamadas, torna-se vazia
  4. O navegador inicia sua redesenhar trabalho, mas leva em conta que há um retorno de chamada registrado. Então ele remove esse registro (porque ele deve ser executado somente uma vez) e executa update antes de fazer qualquer outra coisa.
  5. A largura mudanças de horários de uma necessidade de repintura. A lista de alterações agora inclui a alteração do plano de fundo e este largura alterar e qualquer efeito cascata que tenha sido calculado. (Como isso é representado é um browser dependentes)
  6. O update a função é registado como retorno de chamada novamente.
  7. O navegador agora verifica o que ele precisa fazer, como parte deste trabalho de redesenhar e executa tudo o que é necessário para visualizar os efeitos do plano de fundo e as alterações de largura.
  8. O trabalho de pintura termina. Tudo o que resta é registrado update de retorno de chamada.
  9. Quando o navegador executa sua próxima pintura ciclo, comece novamente a partir do passo 4, mas agora não há fila de espera de fundo-alterar mais. Para o resto vai ser o mesmo processo.
2021-11-21 12:57:10

"4. O navegador inicia seu layout/redesenho de trabalho," que é muito confuso formulação, acho dizendo que "o navegador começa a atualizar o rendering" seria um pouco menos confuso. O layout e a redesenhar são separados, você pode muito bem forçar um layout de forma síncrona do usuário-terra de código, você não pode forçar um repaint, que será sempre a última etapa do processamento passos. Além disso, sinto que a resposta à primeira pontos seria muito mais simples, lembrando partir do get-go, que raf(()=>raf(fn2)) irá agendar fn2 para acionar o próximo quadro. Caso contrário, esta resposta está correta.
Kaiido

@Kaiido, obrigado pelo seu comentário. "você pode muito bem forçar um layout de forma síncrona do usuário-terra code": quer dizer que um usuário perceptível alteração no layout? você pode dar um exemplo de código que?
trincot

De qualquer forma, eu removida a referência para o layout.
trincot

gist.github.com/paulirish/5d52fb081b3570c81e3a Aqui está uma lista de o que desencadeia o layout, e sim, é "user-se perceptível": stackoverflow.com/questions/55134528/...
Kaiido

Tudo Bem, Kaiido!
trincot

Em outros idiomas

Esta página está em outros idiomas

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