предисловие
Сегодня, катаясь на своем любимом электрическом ослике, я шла по улице в раздумьях, и вдруг передо мной появился мальчик на вынос Ele.me, а в правом нижнем углу коробки на вынос было внушительно написано .Carbon Fiber(碳纤维)
,оказалосьFiber
Его тоже можно использовать! ! ! Такое чувство, что я открыл свои две вены Рена и Ду, и я в одно мгновение оказался прав.Fiber
Понимание этого слова улучшилось как на дрожжах! Используется инкубатор.Carbon Fiber
, Кажется, что это действительно большое усилие!
React
Команда переписалаReact
Основной алгоритм ---reconciliation
, предыдущий алгоритм обычно называетсяstack reconciliation
, теперь называетсяfiber reconciliation
.
существуетReact Fiber
После того, как архитектура вышла, она вызвала настоящий ажиотаж.React
Почему команда переписалаReact
архитектура, при этомFiber
Что это такое? пойдем вместеFiber
.
1. Проблемы с React V15.x
В сценариях с большим количеством элементов страницы, которые необходимо часто обновлять,React V15.x
Происходит падение кадров. Вот очень классический пример:
Ссылка на ссылку:Клаудио pro.GitHub.IO/react-fiber…
На изображении выше вы можете увидеть очевидный феномен пропуска кадров. Причина в том, что большое количество синхронных вычислительных задач блокирует работу браузера.UI
оказывать. Потому что по умолчаниюJS
Операции, макет страницы и отрисовка страницы выполняются в основном потоке браузера и являются взаимоисключающими. еслиJS
Операция продолжает занимать основной поток, и страница не может быть обновлена вовремя. когда мы звонимsetState
При обновлении страницы,React
Он пройдет по всем узлам приложения, рассчитает разницу, а затем обновитUI
. Весь процесс нельзя прерывать. Если на странице много элементов, весь процесс может занять более16ms
, легко пропустить кадры.
существуетDom-Diff
То же самое верно и для рекурсивного сравнения обхода, и есть две проблемы, которые очень сильно влияют на производительность:
- Когда узел дерева огромен, это приводит к тому, что стек выполнения рекурсивных вызовов становится все глубже и глубже.
- Выполнение нельзя прервать, страница будет ждать завершения рекурсивного выполнения перед повторным рендерингом.
Для решения этой проблемы,React
Команда сталкивается с уровня каркасаweb
Рабочий механизм страницы был оптимизирован, и это дало хорошие результаты. Схема эффекта выглядит следующим образом:
Во-вторых, как решить
Решите проблему, что основной поток заблокирован в течение длительного времени JS
Основная идея задачи о занятии операции состоит в том, чтобы разделить операцию на несколько шагов и выполнять их партиями. То есть после выполнения некоторых задач управление возвращается браузеру, чтобы у браузера было время отобразить страницу. Подождите, пока браузер не будет занят, прежде чем продолжить ранее незавершенную задачу.
React
Разделяйте задачи на маленькие части и выполняйте их в короткие промежутки времени.分片任务
, позвольте основному потоку делать дела с более высоким приоритетом, и если есть что-то ожидающее, вернуться, чтобы закончить работу. ОдинFiber
это единица работы,React
Основная концепцияUI
является проекцией данных, суть компонента можно рассматривать как входные данные, выходныеUI
описание информации (虚拟DOM树
),который:
ui = f(data)
То есть рендерингReact app
, на самом деле вызывает функцию. Функция сама будет вызывать другие функции для формирования стека вызовов. Стек вызовов, вызванный рекурсивным вызовом, находится вне нашего контроля и может быть выполнен только один раз. а такжеFiber
Просто чтобы решить эту проблему, вы можете прерывать стек вызовов по мере необходимости и вручную управлятьstack frame
- В этой связи,Fiber
можно понимать как virtual stack frame
.
старая версияReact
Рекурсивный рендеринг с использованиемJS
Стек вызовов функций самого движка, он будет выполняться до тех пор, пока стек не опустеет. а такжеFiber
Реализован собственный стек вызовов компонентов, который обходит дерево компонентов в виде связанного списка и может гибко приостанавливать, возобновлять и отбрасывать выполненные задачи. Способ сделать это использовать браузерrequestIdleCallback
этоAPI
. Официальное объяснение таково:
window.requestIdleCallback()会在浏览器空闲时期依次调用函数,这就可以让开发者在主事件循环中执行后台和低优先级的任务,而且不会对像动画和输入响应等用户交互这些延迟触发但关键的事件产生影响。函数一般会按先进先调用的顺序执行,除非函数在浏览器调用它之前就到了它的超时时间。
Справочная документация:developer.Mozilla.org/this-cn/docs/…
Разделение волокна
Поскольку задача должна быть разделена на небольшие задачи, должен быть разделенный план.
Fiber
Схема разделения основана на виртуальномDOM
разделить, потому чтоfiber tree
основывается наVirtual DOM tree
Структура та же, но информация, которую несут узлы, отличается.
Таким образом, каждый экземпляр компонента и каждыйDOM
Абстрактное представление узла — это единица работы, которая обрабатывается по одной в рабочем цикле.fiber
, После обработки одного он определит, есть ли задачи с высоким приоритетом или достаточно ли оставшегося времени, и может продолжить обработку, приостановить или завершить рабочий цикл.
Рабочий цикл согласования оптоволокна
- Найдите корневой узел с наивысшим приоритетом
workInProgress tree
, в зависимости от обрабатываемого узла (представляющего компонент или узел DOM) - Проверяем, нужно ли обновлять текущий узел, если нет, переходим сразу к 4
- отметить это
tag
), обновить себя (обновление компонентаprops
,context
Ждать,DOM
примечание к узлуDOM change
),провестиreconcileChildren
и вернутьсяworkInProgress.child
- не существует
workInProgress.child
, оказывается листовым узлом, собираем вверхeffect
- Пучок
child
илиsibling
так какnextUnitWork
, введите следующий рабочий цикл. если обратноworkInProgress tree
корневой узел, рабочий цикл заканчивается - Войти
commit
сцена
Рабочая фаза волокна
-
diff render
а такжеreconciliation
в основном строятworkInProgress tree
,Фактическиdiff
Обработать -
complete diffProperties
,отметкаtag
,собиратьeffect
-
commit
Стадия фиксации, применение обновлений
Технология workInProgress с двойным буферным пулом
Fiber调度算法
Взятый双缓冲池算法
,FiberRoot
Все узлы ниже попытаются создать свои собственные «зеркала» в процессе работы алгоритма.
workInProgress tree
даreconcile
процесс изfiber tree
Снимок текущего прогресса создан, вся работа выполняется в этом дереве, используется для расчета обновлений, завершенияreconciliation
Обработать.
workInProgress.alternate = current;
current.alternate = workInProgress;
он и токfiber
пройти черезalternate
создавать ассоциации, строитьworkInProgress
, возьметcurrent.alternate
, повторно используйте, если он существует, и создайте, если он не существует. Это позволяет повторно использовать внутренние объекты (fiber
), экономя выделение памяти,GC
стоимость времени.
workInProgress tree
После завершения строительства получается новыйfiber tree
, при входеcommit
сценаcurrent
указал наworkInProgress
.
root.current = finishedWork;
Основная идея — технология двойного буферного пула (double buffering pooling technique
), потому что необходимо сделатьdiff
Если да, то следует сравнить как минимум два дерева. Таким образом, общее количество деревьев может быть ограничено до2
, узлы и атрибуты узлов создаются лениво, чтобы свести к минимуму рост использования памяти из-за процесса алгоритма.
Двойная буферизация двух деревьевFiberNode Tree
обмен ролями, оригиналworkInProgress
Правильный.
Стратегия обновления с двойной буферизацией
- После каждого рендеринга
fiber
присвоение дереваcurrentRoot
- Первое обновление будет
rooterFiber
изalternate
Укажите на последний визуализированныйcurrentRoot
- Обновления после второго будут
workInProgressRoot
направлениеcurrentRoot.alternate
, то токworkInProgressRoot.alternate
Укажите на последний визуализированныйcurrentRoot
- ...
- добиться повторного использования
fiber
дерево объектов
После того, как у нас есть представление о проблеме, давайте посмотримReact
как именно.
3. Решения
React
Внутреннюю работу фреймворка можно разделить на 3 уровня:
-
Virtual DOM
Слой, который описывает, как выглядит страница. -
Reconciler
уровень, отвечающий за вызов методов жизненного цикла компонента, выполнениеDiff
операции и др. -
Renderer
Слой, в зависимости от разных платформ, отображает соответствующую страницу, чем чащеReactDOM
а такжеReactNative
.
следовательноVirtual DOM
,Dom diff
,Fiber
,Renderer
И т.д. это не отдельное понятие! Скорее, они взаимосвязаны и дополняют друг друга!
Среди них больше всего изменился слой Reconciler, и команда React также дала ему новое имя:Fiber Reconciler
. то естьFiber
.
Fiber
На самом деле это относится к структуре данных, которую можно использовать с чистымJS
объект для представления:
const fiber = {
stateNode, // 节点实例
child, // 子节点
sibling, // 兄弟节点
return, // 父节点
}
Чтобы отличить предыдущийReconciler
Назван какStack Reconciler
.Stack Reconciler
Процесс операции нельзя прерывать, и он должен идти до темноты:
а такжеFiber Reconciler
Каждый раз, когда он выполняется в течение определенного периода времени, управление возвращается браузеру, который может выполняться по секциям:
Для того, чтобы добиться такого эффекта, необходимо иметь планировщик (
Scheduler
) ставить задачи. Существует шесть приоритетов задач:
-
synchronous
, с предыдущимStack Reconciler
Та же операция, синхронное выполнение -
task
,существуетnext tick
выполнить до -
animation
, выполняется перед следующим кадром -
high
, который будет выполнен немедленно в ближайшее время -
low
, не беда, если выполнение немного задержится -
offscreen
,в следующий разrender
время илиscroll
выполнить, когда
Задачи с высоким приоритетом (например, ввод с клавиатуры) могут прерывать задачи с низким приоритетом (например,diff
) выполняется для более быстрого вступления в силу.
Fiber Reconciler
В процессе выполнения он будет разделен на 2 этапа:
- первый этап, генерация
Fiber
дерево и получить информацию об узле, которую необходимо обновить. Этот шаг является постепенным процессом и может быть прерван. - На втором этапе узлы, которые необходимо обновить, обновляются пакетно, и этот процесс нельзя прерывать.
Фаза 1 может быть прервана, позволяя выполнять задачи с более высоким приоритетом в первую очередь, что значительно снижает вероятность пропуска кадров страницы на уровне фреймворка.
Fiber
специальность:
- Приостановить работу и вернуться к ней позже
- Может расставлять приоритеты для разных видов работы
- Повторное использование ранее выполненной работы
- Завершить работу, которая больше не нужна
Четыре,Fiber
Дерево
Fiber Reconciler
на первом этапеDiff
При расчете аFiber
Дерево. это деревоVirtual DOM
Он генерируется путем добавления дополнительной информации на основе дерева, которое по сути представляет собой связанный список.
Fiber
Деревья генерируются по одному при первом рендеринге. позже нужноDiff
, на основе существующего дерева и последнихVirtual DOM
информации, генерировать новое дерево, и каждый раз, когда новое дерево генерирует новый узел, оно будет возвращать управление основному потоку, чтобы проверить, есть ли задачи с более высоким приоритетом, которые необходимо выполнить. Если нет, продолжайте процесс построения дерева:
Если в процессе есть задача с более высоким приоритетом, которую необходимо выполнить, тоFiber Reconciler
Генерируемое дерево будет отброшено, и оно будет выполнено снова, когда оно будет бездействовать.
в разработкеFiber
в процессе дерева,Fiber Reconciler
Информация об узле, которую необходимо обновить, будет сохранена вEffect List
Среди них, когда выполняется второй этап, соответствующие узлы будут обновляться пакетами.
Фаза выполнения волокна
Каждый рендер состоит из двух фаз:Reconciliation
(координацияrender
) стадия иCommit
(совершить) этап
- координация
render
Стадия: можно рассматривать какDiff
этап, этот этап можно прервать, на этом этапе будут обнаружены все изменения узла, такие как добавление узла, удаление и т. д., эти изменения находятся вReact
называется вEffect
(побочный эффект) - Этап фиксации: выполнение побочных эффектов, рассчитанных на предыдущем этапе, которые необходимо обработать за один раз. Эта стадия не может быть прервана и должна выполняться синхронно одновременно.
Сводка по волокну
- Мы можем разумно распределить с помощью некоторых стратегий планирования
CPU
ресурсы для повышения отзывчивости пользователей - пройти через
Fiber
архитектура, сделай самReconciliation
Процесс становится прерывистым, уступая в свое времяCPU
Права на выполнение, которые позволяют браузеру своевременно реагировать на действия пользователя.
V. Резюме
нас从React V15
Исходя из существующих проблем, введениеReact Fiber
идеи решения проблем и представляетFiber Reconciler
рабочий процесс. отStack Reconciler
прибытьFiber Reconciler
, на исходном уровне рекурсия заменена на цикл, что решает проблемуReact V15
существующие проблемы.
Шесть, анализ исходного кода
scheduler
существуетReact16.5
тогда поставьscheduler
Отправьте посылку самостоятельно, просто позвонитеscheduler
scheduleCallbackWithExpirationTime
Асинхронныйroot
Планирование задач осуществляется с помощью этого метода.Самое главное здесь - вызватьscheduler
изscheduleDeferredCallback
метод (вscheduler
пакетschedulework
) функция обратного вызова входящего событияperformAsyncWork
, и содержащийtimeout
Объект события тайм-аута
function scheduleCallbackWithExpirationTime(
root: FiberRoot,
expirationTime: ExpirationTime,
) {
if (callbackExpirationTime !== NoWork) {
// A callback is already scheduled. Check its expiration time (timeout).
if (expirationTime > callbackExpirationTime) {
// Existing callback has sufficient timeout. Exit.
return
} else {
if (callbackID !== null) {
// Existing callback has insufficient timeout. Cancel and schedule a
// new one.
cancelDeferredCallback(callbackID)
}
}
// The request callback timer is already running. Don't start a new one.
} else {
startRequestCallbackTimer()
}
callbackExpirationTime = expirationTime
const currentMs = now() - originalStartTimeMs
const expirationTimeMs = expirationTimeToMs(expirationTime)
const timeout = expirationTimeMs - currentMs
// 最主要的就是调用了scheduler的scheduleDeferredCallback方法
callbackID = scheduleDeferredCallback(performAsyncWork, { timeout })
}
scheduler.scheduleWork
Создайте узел планировщикаnewNode
, и следуйтеtimeoutAt
порядок добавления вCallbackNode
связанный список, звонитеensureHostCallbackIsScheduled
здесьexpirationTime
передается при вызовеtimeoutAt
Добавьте время истечения, сформированное текущим временем.
function unstable_scheduleCallback(callback, deprecated_options) {
var startTime =
currentEventStartTime !== -1 ? currentEventStartTime : getCurrentTime()
var expirationTime
if (
typeof deprecated_options === 'object' &&
deprecated_options !== null &&
typeof deprecated_options.timeout === 'number'
) {
// FIXME: Remove this branch once we lift expiration times out of React.
expirationTime = startTime + deprecated_options.timeout
} else {
// 这里是以后把`expirationTime`从React中抽离出来之后的逻辑
}
var newNode = {
callback,
priorityLevel: currentPriorityLevel,
expirationTime,
next: null,
previous: null,
}
// Insert the new callback into the list, ordered first by expiration, then
// by insertion. So the new callback is inserted any other callback with
// equal expiration.
if (firstCallbackNode === null) {
// This is the first callback in the list.
firstCallbackNode = newNode.next = newNode.previous = newNode
// 调用ensureHostCallbackIsScheduled
ensureHostCallbackIsScheduled()
} else {
var next = null
var node = firstCallbackNode
do {
if (node.expirationTime > expirationTime) {
// The new callback expires before this one.
next = node
break
}
node = node.next
} while (node !== firstCallbackNode)
if (next === null) {
// No callback with a later expiration was found, which means the new
// callback has the latest expiration in the list.
next = firstCallbackNode
} else if (next === firstCallbackNode) {
// The new callback has the earliest expiration in the entire list.
firstCallbackNode = newNode
ensureHostCallbackIsScheduled()
}
var previous = next.previous
previous.next = next.previous = newNode
newNode.next = next
newNode.previous = previous
}
return newNode
}
ensureHostCallbackIsScheduled
Если обратный вызов уже вызывается, тоreturn
, потому что его продолжали бы называть,isExecutingCallback
существуетflushWork
будет изменен наtrue
. еслиisHostCallbackScheduled
дляfalse
, то есть планирование еще не началось, то установитеtrue
, если он уже начался, отмените его напрямую, потому что порядок может измениться. передачаrequestHostCallback
Начать планирование здесь
function ensureHostCallbackIsScheduled() {
if (isExecutingCallback) {
// Don't schedule work yet; wait until the next time we yield.
return
}
// Schedule the host callback using the earliest expiration in the list.
var expirationTime = firstCallbackNode.expirationTime
if (!isHostCallbackScheduled) {
isHostCallbackScheduled = true
} else {
// Cancel the existing host callback.
cancelHostCallback()
}
requestHostCallback(flushWork, expirationTime)
}
cancelHostCallback = function() {
scheduledHostCallback = null
isMessageEventScheduled = false
timeoutTime = -1
}
requestHostCallback
Начните вводить расписание, установите содержание расписания, используйтеscheduledHostCallback
а такжеtimeoutTime
Эти две глобальные переменные записывают функцию обратного вызова и соответствующее время истечения срока действия.
передачаrequestAnimationFrameWithTimeout
, который на самом деле вызываетrequestAnimationFrame
плюс установить100ms
таймер для предотвращенияrequestAnimationFrame
слишком долго для срабатывания.
обратный звонокanimationTick
и установитьisAnimationFrameScheduled
Глобальная переменнаяtrue
requestHostCallback = function(callback, absoluteTimeout) {
scheduledHostCallback = callback
timeoutTime = absoluteTimeout
if (isFlushingHostCallback || absoluteTimeout < 0) {
// Don't wait for the next frame. Continue working ASAP, in a new event.
window.postMessage(messageKey, '*')
} else if (!isAnimationFrameScheduled) {
isAnimationFrameScheduled = true
requestAnimationFrameWithTimeout(animationTick)
}
}
фиктивный запросIdleCallback
потому чтоrequestIdleCallback
этоAPI
Он все еще находится в стадии черновика, поэтому скорость реализации браузера невысока, так что вот онReact
используется напрямуюpolyfill
строить планы.
Эта схема простоrequestAnimationFrame
Выполните дополнительную обработку, прежде чем браузер отобразит кадр, затем передайтеpostMessage
существуетmacro task
(аналогичныйsetTimeout
) для добавления обратного вызова, потому что дальше браузер перейдет к этапу рендеринга, поэтому вызывается основной потокblock
жизнь,Обратный вызов, когда основной поток свободен
animationTick
если толькоscheduledHostCallback
Продолжай звонитьrequestAnimationFrameWithTimeout
Поскольку этот кадр визуализируется, очередь не может быть очищена, и она будет вызвана снова, поэтому здесь она опущена.requestHostCallback
Необходимость призыва
Следующий фрагмент кода используется для вычисления разделенияrequestAnimationFrame
разница во времени, если эта разница во времени меньше текущей два раза подрядactiveFrameTime
, что указывает на то, что частота кадров платформы очень высока. В этом случае время кадра будет динамически уменьшаться.
последнее обновлениеframeDeadline
, то если нет триггераidleTick
затем отправьте сообщение
var animationTick = function(rafTime) {
if (scheduledHostCallback !== null) {
requestAnimationFrameWithTimeout(animationTick)
} else {
isAnimationFrameScheduled = false
return
}
var nextFrameTime = rafTime - frameDeadline + activeFrameTime
if (nextFrameTime < activeFrameTime && previousFrameTime < activeFrameTime) {
if (nextFrameTime < 8) {
nextFrameTime = 8
}
activeFrameTime =
nextFrameTime < previousFrameTime ? previousFrameTime : nextFrameTime
} else {
previousFrameTime = nextFrameTime
}
frameDeadline = rafTime + activeFrameTime
if (!isMessageEventScheduled) {
isMessageEventScheduled = true
window.postMessage(messageKey, '*')
}
}
idleTick
Судите первымpostMessage
Это ваш собственный, а не возврат напрямую
пустойscheduledHostCallback
а такжеtimeoutTime
Получить текущее время, сравнитьframeDeadline
, проверьте, истекло ли время ожидания, если время ожидания истекло, оцените задачуcallback
Достигнут ли срок годности, если нет, перепроверьте этоcallback
Сделайте отправку, затем вернитесь. Если он придет, установитеdidTimeout
дляtrue
Далее стоит позвонитьcallback
, вот настройкаisFlushingHostCallback
Глобальная переменнаяtrue
Представитель выполняет. и позвониcallback
то естьflushWork
и пройти вdidTimeout
var idleTick = function(event) {
if (event.source !== window || event.data !== messageKey) {
return
}
isMessageEventScheduled = false
var prevScheduledCallback = scheduledHostCallback
var prevTimeoutTime = timeoutTime
scheduledHostCallback = null
timeoutTime = -1
var currentTime = getCurrentTime()
var didTimeout = false
if (frameDeadline - currentTime <= 0) {
if (prevTimeoutTime !== -1 && prevTimeoutTime <= currentTime) {
didTimeout = true
} else {
if (!isAnimationFrameScheduled) {
isAnimationFrameScheduled = true
requestAnimationFrameWithTimeout(animationTick)
}
scheduledHostCallback = prevScheduledCallback
timeoutTime = prevTimeoutTime
return
}
}
if (prevScheduledCallback !== null) {
isFlushingHostCallback = true
try {
prevScheduledCallback(didTimeout)
} finally {
isFlushingHostCallback = false
}
}
}
flushWork
установить первымisExecutingCallback
дляtrue
, представляющий призваниеcallback
настраиватьdeadlineObject.didTimeout
,существует React
Его можно использовать в бизнесе, чтобы определить, истекло ли время ожидания задачи.
еслиdidTimeout
, будет один раз изfirstCallbackNode
Выполнять в обратном порядке до первой задачи с неистекшим сроком действия
Если таймаута нет, то выполнить первыйcallback
, до конца времени кадра
Наконец, очистите переменную, если задача не завершена, вызовите ее снова.ensureHostCallbackIsScheduled
ввести расписание
КстатиImmedia
Приоритетные задачи вызываются снова.
function flushWork(didTimeout) {
isExecutingCallback = true
deadlineObject.didTimeout = didTimeout
try {
if (didTimeout) {
while (firstCallbackNode !== null) {
var currentTime = getCurrentTime()
if (firstCallbackNode.expirationTime <= currentTime) {
do {
flushFirstCallback()
} while (
firstCallbackNode !== null &&
firstCallbackNode.expirationTime <= currentTime
)
continue
}
break
}
} else {
if (firstCallbackNode !== null) {
do {
flushFirstCallback()
} while (
firstCallbackNode !== null &&
getFrameDeadline() - getCurrentTime() > 0
)
}
}
} finally {
isExecutingCallback = false
if (firstCallbackNode !== null) {
ensureHostCallbackIsScheduled()
} else {
isHostCallbackScheduled = false
}
flushImmediateWork()
}
}
flushFirstCallback
то, что он делает, просто
- Если в текущей очереди есть только один обратный вызов, очистить очередь
- Вызовите обратный вызов и передайте
deadline
объект, имеющийtimeRemaining
метод переданframeDeadline - now()
определить, наступило ли время кадра - Если обратный вызов имеет возвращаемое содержимое, добавьте этот возврат в очередь обратного вызова.
ссылка на глобальную переменную
isHostCallbackScheduled
Начато ли планирование, вensureHostCallbackIsScheduled
Установить какtrue
, в конце выполненияcallback
а затем установить наfalse
scheduledHostCallback
существуетrequestHostCallback
значение, как правило,flushWork
, который представляет следующее запланированное действие
isMessageEventScheduled
был ли отправлен вызовidleTick
новости, вanimationTick
установлен вtrue
timeoutTime
Указывает время просроченной задачи, вidleTick
Устанавливается, когда обнаруживается, что время выполнения первой задачи истекло
isAnimationFrameScheduled
начал звонитьrequestAnimationFrame
activeFrameTime
Время рендеринга кадра, по умолчанию 33, то есть 30 кадров в секунду.
frameDeadline
Запишите время истечения текущего кадра, равноеcurrentTime + activeFraeTime
, то есть,requestAnimationFrame
Обратный вызов входящего времени плюс время одного кадра.
isFlushingHostCallback
Это выполняетсяcallback
Справочная документация:Как работает React Fiber и связанные с ним концепции
приложение:
1. Каковы болевые точки React15? Что такое клетчатка? Почему React16 нужно представить Fiber?
- визуализировать и
diff
Этапы выполняются за один раз, и страница застрянет, когда дерево узлов огромно. -
Fiber
не таинственно, простоVirtual-DOM
превратился в链表结构
- Структура связанного списка
requestIdleCallback
Может реализовать прерываемый и восстанавливаемый механизм планирования
2. Виртуальный DOM в React16 такой же, как в React15.
3. Как реализовать структуру данных и алгоритм обхода Fiber?
-
React
используя связанный список вVirtual DOM
связаны, каждый узел представляет собойFiber
4. Как реализовать прерываемое и возобновляемое планирование задач в архитектуре Fiber?
с помощьюrequestIdleCallback
Пусть браузер реализует указанное количество обновлений в простое, отдаваемом после одного кадра рендеринга, а пакетные обновления могут напрямую это пропускатьAPI
, как прежде
5. Как реализовать рендеринг компонентов и сбор и отправку побочных эффектов в архитектуре Fiber?
- Выполняемый порядок сбора аналогичен предварительному обходу двоичного дерева.
- Завершенный порядок сбора аналогичен обходу двоичного дерева в обратном порядке.
6. Как реализовать стратегию оптимизации согласования и двойной буферизации в Fiber?
- существует
Fiber
добавить один в структуруalternate
Идентификатор поля отображался последнимFiber
дерево, повторно используемое для следующего рендера
Выше это то, что яFiber
Поверхностное понимание, если есть какие-либо ошибки, пожалуйста, поправьте меня~~~