всякий раз, когда происходит какая-либо манипуляция DOM, такая как вставка элемента DOM, вызовет перерисовку и, скорее всего, за ней последует перекраска
Действие рисования происходит асинхронно, поэтому "триггер" следует понимать именно так. Сначала ваш код JavaScript завершится до того, как это произойдет на самом деле.
если нам каким-то образом удастся выполнить манипуляцию DOM внутри этого rAF (редактировать: а также поставить в очередь другой rAF в конце), который каждый раз запускает перерисовку и, следовательно, перерисовку, мы застрянем в бесконечном цикле, фактически ничего не отображая на экране.
Потребности в перекраске накапливаются и не удовлетворяются синхронно. Сначала ваш код должен быть завершен до тех пор, пока стек вызовов не опустеет. Таким образом, здесь нет бесконечного цикла.
Или это тот случай, когда, как только браузер решил сделать перекраску, он будет придерживаться ее и применять любые обновления, которые произошли при обратном вызове RAF, при следующей перекраске?
ДА. Когда вызывается обратный вызов RAF, этот код получает последний шанс внести обновления в DOM, что может привести к дальнейшему накоплению потребностей в покраске. Если в этом обратном вызове вы также зарегистрируете другой обратный вызов на RAF, он будет выполнен не в это время, а позже: в следующий раз, когда браузер подготовит свою задачу перерисовки-так что не текущую.
Упрощенный пример
Допустим, у вас есть этот код:
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);
}
Когда это выполняется, мы получаем следующую последовательность:
update
зарегистрирован как обратный вызов
- Изменение фона указывает на необходимость перекраски
- Стек вызовов становится пустым
- Браузер начинает свою работу по перекраске, но учитывает, что есть зарегистрированный обратный вызов. Таким образом, он удаляет эту регистрацию (потому что она должна выполняться только один раз) и выполняет
update
прежде чем делать что-либо еще.
- Изменение ширины указывает на необходимость перекраски. Список изменений теперь включает изменение фона и это изменение ширины, а также любой рассчитанный каскадный эффект. (То, как это представлено, зависит от браузера)
- То
update
функция снова регистрируется как обратный вызов.
- Теперь браузер проверяет, что ему нужно сделать в рамках этой работы по перекраске, и выполняет все необходимое для визуализации эффектов изменения фона и ширины.
- Работа с краской заканчивается. Все, что осталось, - это зарегистрированный
update
обратный звонок.
- Когда браузер выполнит свой следующий цикл рисования, мы начнем снова с шага 4, но теперь в очереди больше нет изменения фона. В остальном это будет тот же самый процесс.
raf(()=>raf(fn2))
будет планироватьfn2
чтобы выстрелить в следующий кадр. В противном случае этот ответ верен.