В первых двух статьях мы проанализировали реализацию, монтаж и жизненный цикл компонентов React. В процессе чтения исходного кода мы часто видим такие вещи, какtransaction
а такжеUpdateQueue
Такой код, который включает в себя две концепции в React: транзакции и очереди обновлений. Поскольку мы рассмотрели их в предыдущих статьях, эта статья основана на том, что всем знакомо.setState
методы для изучения механизмов транзакций и обновления очередей.
1.setState связан
в первой статье«Анализ исходного кода React (1): внедрение и установка компонентов»мы уже знаем, что поclass
Заявленный прототип компонента имеетsetState
метод:
Этот метод передает два параметраpartialState
а такжеcallBack
, первое — это новое значение состояния, а второе — функция обратного вызова. а такжеupdater
определяется в конструкторе:
Как можно заметитьupdater
Он передается конструктором, поэтому найдите, где его выполнить.new ReactComponent
, ты можешь найтиupdater
что. с пользовательскими компонентамиReactCompositeComponent
Например, в_constructComponentWithoutOwner
метод, мы нашли его следы:
return new Component(publicProps, publicContext, updateQueue);
Обнаружение соответствующего параметраupdater
На самом деле этоupdateQueue
. Далее посмотримthis.updater.enqueueSetState
серединаenqueueSetState
Что это:
getInternalInstanceReadyForUpdate
Цель метода — получить текущий объект компонента и присвоить егоinternalInstance
Переменная. Затем оцените, существует ли очередь обновления состояния текущего объекта компонента, и если да, то она будетpartialState
То есть в очередь добавляется новое значение состояния, если его нет, создается очередь обновления объекта, и можно отметить, что очередь существует в виде массива. Давайте посмотрим на последний звонокenqueueUpdate
Что делает метод:
Видно из кода, когдаbatchingStrategy.isBatchingUpdates
дляfalse
, исполнитсяbatchedUpdates
очередь обновления, еслиtrue
, поместите компонент вdirtyComponent
середина. Давайте посмотримbatchingStrategy
Исходный код:
Грубо говоря, начальное значение isBatchingUpdates равноfalse
,а такжеbatchedUpdates
Внутренне выполнить входящую функцию обратного вызова.
Кажется, что такая длинная логика немного сбивает с толку, но из этих кодов мы смутно понимаем, что React не обновляет компоненты случайно, а выполняет их через оценку состояния (например, true/false). На самом деле React использует концепцию «конечной машины» внутри: когда компоненты находятся в разных состояниях, логика выполняется по-разному. Взяв в качестве примера процесс обновления компонентов, React обновляет компоненты в форме транзакции + состояния, поэтому давайте обсудим механизм транзакций далее.
2. транзакция транзакция
Сначала посмотрите на диаграмму анализа официального исходного кода:
<pre>
* wrappers (injected at creation time)
* + +
* | |
* +-----------------|--------|--------------+
* | v | |
* | +---------------+ | |
* | +--| wrapper1 |---|----+ |
* | | +---------------+ v | |
* | | +-------------+ | |
* | | +----| wrapper2 |--------+ |
* | | | +-------------+ | | |
* | | | | | |
* | v v v v | wrapper
* | +---+ +---+ +---------+ +---+ +---+ | invariants
* perform(anyMethod) | | | | | | | | | | | | maintained
* +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
* | | | | | | | | | | | |
* | | | | | | | | | | | |
* | | | | | | | | | | | |
* | +---+ +---+ +---------+ +---+ +---+ |
* | initialize close |
* +-----------------------------------------+
* </pre>
Из блок-схемы это очень просто, каждый метод будетwrapper
упаковано, надо использоватьperform
Вызывается, выполняется до и после обернутого методаinitialize
а такжеclose
. Примеры обычных функций иwrapper
В чем разница, когда выполняется обернутая функция:
function method(){
console.log('111')
};
transaction.perform(method);
//执行initialize方法
//输出'111'
//执行close方法
мы знаем, что предыдущийbatchingStrategy
в кодеtransaction.perform(callBack)
Фактический вызовtransaction.perform(enqueueUpdate)
,ноenqueueUpdate
метод все еще существуетtransaction.perform(enqueueUpdate)
Разве это не создает бесконечный цикл?
Чтобы избежать проблемы возможного бесконечного цикла,wrapper
проявляется эффект. Давайте посмотрим на эти дваwrapper
Как это определяется:
Как видно из приведенной выше ментальной карты,isBatchingUpdates
Начальное значениеfalse
, когда выполняется как транзакцияtransaction.perform(enqueueUpdate)
, фактический поток выполнения выглядит следующим образом:
// RESET_BATCHED_UPDATES.initialize() 实际为空函数
// enqueue()
// RESET_BATCHED_UPDATES.close()
Используйте блок-схему, чтобы проиллюстрировать:
На словах этоRESET_BATCHED_UPDATES
этоwrapper
Роль заключается в том, чтобы установитьisBatchingUpdates
То есть значение состояния обновления компонента.Если у компонента есть запрос на обновление, он устанавливается в состояние обновления, а исходное состояние восстанавливается после завершения обновления.
Что хорошего в этом? Конечно, чтобы избежать повторения компонента рендеринга, улучшите его производительность ~
RESET_BATCHED_UPDATES
Для измененияisBatchingUpdates
логическое значениеfalse
илиtrue
,ЭтоFLUSH_BATCHED_UPDATES
Какова роль? На самом деле можно примерно догадаться, что его роль заключается в обновлении компонентов.Давайте сначала разберемся.FLUSH_BATCHED_UPDATES.close()
Логика реализации:
можно увидетьflushBatchedUpdates
Метод петлей через всеdirtyComponents
, Но также в форме транзакции вызоваrunBatchedUpdates
метод, потому что исходный код длинный, поэтому вот две вещи, которые делает этот метод:
- Один из них заключается в реализации
updateComponent
метод обновления компонента - Во-вторых, если
setState
Если функция обратного вызова передается в метод, функция обратного вызова сохраняется вcallbackQueue
очередь.
посмотриupdateComponent
Исходный код:
можно увидеть казненнымcomponentWillReceiveProps
Методы иshouldComponentUpdate
метод. Одна из вещей, которую нельзя игнорировать, это то, чтоshouldComponentUpdate
раньше, казненный_processPendingState
метод, давайте посмотрим, что делает эта функция:
Эта функция в основномstate
Обрабатывать:
1. Если очередь обновленийnull
, затем вернитесь к исходномуstate
;
2. Если в очереди обновлений есть обновление, вернуть значение обновления;
3. Если в очереди обновлений несколько обновлений, объедините их с помощью цикла for;
Таким образом, в жизненном цикле объясняется,componentShouldUpdate
Перед казнью всеstate
Изменения будут объединены и, наконец, обработаны единообразно.
назад_updateComponent
, и, наконец, еслиshouldUpdate
дляtrue
,воплощать в жизнь_performComponentUpdate
метод:
После грубого просмотра вы обнаружите, что та же процедура все еще выполняется.componentWillUpdate
Метод жизненного цикла, выполняемый после завершения обновленияcomponentDidUpdate
метод. Давайте посмотрим на обновление_updateRenderedComponent
метод:
Идея этого кода очень ясна:
- Получить информацию о старом компоненте
- Получить информацию о новом компоненте
-
shouldUpdateReactComponent
Это метод (далее указанный какshould
Функция), определяется, обновлять ли старые и новые компоненты переданной информации. -
should
возврат функцииtrue
, чтобы выполнить обновление старого компонента. -
should
возврат функцииfalse
, который выполняет размонтирование старого компонента и монтирование нового компонента.
В сочетании с предыдущей блок-схемой мы дополняем весь процесс обновления компонентов:
4. Пишите в конце
(1)setState
Перезвоните
setState
функция обратного вызова сstate
Процесс аналогичен,state
Зависит отenqueueSetState
обработка, функция обратного вызоваenqueueCallback
разобраться, заинтересованные читатели могут изучить самостоятельно.
(2) ОsetState
авария, вызванная
Мы уже знаем,this.setState
на самом деле называетсяenqueueSetState
, когда компонент обновляется, потому что новыйstate
Он еще не был объединен, поэтому следующееperformUpdateIfNecessary
в кодеthis._pendingStateQueue
дляtrue
:
Слияниеstate
После того, как React будетthis._pendingStateQueue
Установить какnull
,такdirtyComponent
При переходе к следующей пакетной обработке обновленные компоненты не войдут в повторный процесс, гарантируя, что компоненты выполнят операцию обновления только один раз.
так что не вcomponentWillUpdate
вызыватьsetState
Причина в том, чтоsetState
закажу_pendingStateQueue
дляtrue
, что приводит к повторному выполнениюupdateComponent
Потом снова позвонюcomponentWillUpdate
, последний цикл вызываетcomponentWillUpdate
вызвать сбой браузера.
(3) О внедрении зависимостей React
В предыдущем коде у нас есть логотип очереди обновления.batchingStrategy
, переходим непосредственно кReactDefaultBatchingStrategy
Анализ, это из-за большого количества инъекций зависимостей внутри React. Когда React инициализируется,ReactDefaultInjection.js
вводить вReactUpdates
в качестве стратегии по умолчанию. Внедрение зависимостей имеет большое количество применений в рендеринге React на стороне сервера, и заинтересованные студенты могут изучить его самостоятельно.
рассмотрение:
«Анализ исходного кода React (1): внедрение и установка компонентов»
«Анализ исходного кода React (2): жизненный цикл компонентов»
«Анализ исходного кода React (4): система событий»
Контактный адрес электронной почты: sssyoki@foxmail.com