ИсследованиеsetState
Этот вопрос возникает из-за сомнения: при использовании reduxdispatch
Одинaction
, почему это может привести к обновлению представления?
Первое предположениеstore
После изменения куда-то позвонил редуксsetState
, который сообщает реагировать.
Я посмотрел на код и обнаружил, что это действительно так, позвонивdispatch action
вызоветonStateChange
функция (эта функция находится вconnect
был зарегистрирован наstore
,store
одеялоreducer
Запускается после модификации),onStateChange
функция определения необходимостиshouldComponentUpdate
затем выполнитьthis.setState({})
для запуска реагирующих обновлений.
Итак, возникает вопрос:
- Зачем
setState
Можно сделать обновление вида, как это происходит пошаговоvirtualDOM
а затем визуализировалось -
setState
Почему производительность иногда асинхронна, а иногда синхронна? - Почему в функции жизненного цикла
willReceiveProps
могуsetState
а такжеwillUpdate
нет?
После обводки процесса мы получаем следующий рисунок.На рисунке функция, которую нужно выполнить, стоит перед двоеточием каждого блока процесса:
Кратко опишу процесс:
-
setState
После входящегоstate
поставить в очередьqueue
,enqueueUpdate
метод будет основан наisBatchingUpdate
Отметить битовое суждение, если компонент в настоящее время обновляется, текущий компонент будет размещен непосредственноdirtyComponents
массив, иначеisBatchingUpdate
Установите значение true и включите «массовое обновление (batchedUpdates
)" транзакции (transaction
).
Проще говоря, так называемая
Transaction
это то, что нужно будет реализоватьmethod
использоватьwrapper
упакованы, а затем переданыTransaction
который предоставилperform
метод выполняется. пока вperform
перед этим выполнить всеwrapper
серединаinitialize
方法;perform
После завершения (т.method
после выполнения), а затем выполнить всеclose
метод. Группаinitialize
а такжеclose
метод, называемыйwrapper,
Transaction
поддерживает несколькоwrapper
наложение.
После того, как транзакция открыта, она будет выполняться последовательноinitialize、perform、close
метод. можно увидеть,batchedUpdates
существуетperform
этап будет выполнен сноваenqueueUpdate
метод, посколькуisBatchingUpdate
уже верно, поэтому поместит текущий компонент вdirtyComponents
. ключclose
стадия, еслиdirtyComponents
Если он пустой, значит обновление не требуется, иначе он начнет обновляться и включитсяflushBatchedUpdates
дела.
-
flushBatchedUpdates
существуетperform
этап будетdirtyComponents
компоненты в父 > 子
Порядок компонентов вызывает метод обновления, и компоненты будут выполняться последовательно при их обновлении:
willReceiveProps -> 将 queue 中缓存的 state 与缓存的 state 合并 -> shouldComponentUpdate。
Если определено, что требуется обновление, выполнитеrender
способ получить новыйreactElement
, сравните его с предыдущимreactElement
Просто выполните diff и передайте результаты diff (удалить, переместить и т. д.) черезsetInnerHTML
Просто подождите, пока метод инкапсуляции обновит представление, и детали можно увидеть на рисунке.
-
flushBatchedUpdates
существуетclose
этап будет проверен сноваdirtyComponents
Изменилась ли длина, если изменилась, значит, есть новаяdirtyComponent
, нужно сделать это сноваflushBatchedUpdates
.
НаполнятьupdateComponent
Код:
// 更新组件
updateComponent: function(transaction, prevParentElement, nextParentElement) {
var prevContext = this.context;
var prevProps = this.props;
var nextContext = prevContext;
var nextProps = prevProps;
if (prevParentElement !== nextParentElement) {
nextContext = this._processContext(nextParentElement._context);
nextProps = this._processProps(nextParentElement.props);
// 当前状态为 RECEIVING_PROPS
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
// 如果存在 componentWillReceiveProps,则执行
if (this.componentWillReceiveProps) {
this.componentWillReceiveProps(nextProps, nextContext);
}
}
// 设置状态为 null,更新 state
this._compositeLifeCycleState = null;
var nextState = this._pendingState || this.state;
this._pendingState = null;
var shouldUpdate =
this._pendingForceUpdate ||
!this.shouldComponentUpdate ||
this.shouldComponentUpdate(nextProps, nextState, nextContext);
if (!shouldUpdate) {
// 如果确定组件不更新,仍然要设置 props 和 state
this._currentElement = nextParentElement;
this.props = nextProps;
this.state = nextState;
this.context = nextContext;
this._owner = nextParentElement._owner;
return;
}
this._pendingForceUpdate = false;
......
// 如果存在 componentWillUpdate,则触发
if (this.componentWillUpdate) {
this.componentWillUpdate(nextProps, nextState, nextContext);
}
// render 递归渲染
var nextMarkup = this._renderedComponent.mountComponent(
thisID,
transaction,
this._mountDepth + 1
);
// 如果存在 componentDidUpdate,则触发
if (this.componentDidUpdate) {
transaction.getReactMountReady().enqueue(
this.componentDidUpdate.bind(this, prevProps, prevState, prevContext),
this
);
}
},
Весь процесс может ответить на некоторые из предыдущих сомнений:
- Зачем
setState
затем журнал, иногдаstate
Не сразу, а иногда?
в жизненном циклеsetState
в большомtransaction
, В настоящее времяisBatchingUpdate
дляtrue
,воплощать в жизньsetState
Сделает толькоdirtyComponents
Массив толкает текущий компонент без дальнейшей обработки. В это время журнал смотрит на негоstate
Все еще никаких изменений. тогда как если вне транзакции, например.setTimeout
внутриsetState
,В настоящее времяisBatchingUpdate
дляfalse
, он будет выполнен непосредственно до измененияstate
, значит лог выходит в это времяstate
поменяли сразу. следовательноСинхронность setState не гарантируется, а не то, что она должна быть асинхронной..
2. Все в одномtranaction
, почему вwillReceiveProps
также можетsetState
, пока вshouldComponentUpdate
а такжеwillUpdate
когдаsetState
Не приведет ли это к бесконечному циклу в браузере?
Внутри компонента есть флаг_compositeLifeCycleState
Представляет текущее состояние жизненного цикла вwillReceiveProps
ранее был установлен наRECEIVING_PROPS
,существуетwillReceiveProps
установлен на ноль после выполнения, в то время какperformUpdateIfNecessary
В текущем состоянии функцииMOUNTING
илиRECEIVING_PROPS
не будет продолжать звонитьupdateComponent
функция.
performUpdateIfNecessary: function(transaction) {
var compositeLifeCycleState = this._compositeLifeCycleState;
// ■■■■■■■■重点■■■■■■■■■■■■
// 当状态为 MOUNTING 或 RECEIVING_PROPS 时,则不更新
if (compositeLifeCycleState === CompositeLifeCycle.MOUNTING ||
compositeLifeCycleState === CompositeLifeCycle.RECEIVING_PROPS) {
return;
}
var prevElement = this._currentElement;
var nextElement = prevElement;
if (this._pendingElement != null) {
nextElement = this._pendingElement;
this._pendingElement = null;
}
// 调用 updateComponent
this.updateComponent(
transaction,
prevElement,
nextElement
);
}
Таким образом, вwillReceiveProps
ВремяsetState
из-за_compositeLifeCycleState
ужеRECEIVING_PROPS
, не запускает новыйupdateComponent
, пока вwillUpdate
когда_compositeLifeCycleState
был установлен обратно в ноль, поэтому это приведет к следующемуupdateComponent
, а затем снова запускать каждый жизненный цикл компонента, конечно, он неизбежно будет выполнятьсяwillUpdate
, таким образом входя в бесконечный цикл.