当我们有了前面知识的铺垫,就很容易理解this.setState
的工作流程。
# 流程概览
可以看到,this.setState
内会调用this.updater.enqueueSetState
方法。
Component.prototype.setState = function (partialState, callback) {
if (!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null)) {
{
throw Error( "setState(...): takes an object of state variables to update or a function which returns an object of state variables." );
}
}
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
你可以在这里看到这段代码
在enqueueSetState
方法中就是我们熟悉的从创建update
到调度update
的流程了。
enqueueSetState(inst, payload, callback) {
// 通过组件实例获取对应fiber
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
// 获取优先级
const lane = requestUpdateLane(fiber, suspenseConfig);
// 创建update
const update = createUpdate(eventTime, lane, suspenseConfig);
update.payload = payload;
// 赋值回调函数
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
// 将update插入updateQueue
enqueueUpdate(fiber, update);
// 调度update
scheduleUpdateOnFiber(fiber, lane, eventTime);
}
你可以在这里看到
enqueueSetState
代码
这里值得注意的是对于ClassComponent
,update.payload
为this.setState
的第一个传参(即要改变的state
)。
# this.forceUpdate
在this.updater
上,除了enqueueSetState
外,还存在enqueueForceUpdate
,当我们调用this.forceUpdate
时会调用他。
可以看到,除了赋值update.tag = ForceUpdate;
以及没有payload
外,其他逻辑与this.setState
一致。
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const suspenseConfig = requestCurrentSuspenseConfig();
const lane = requestUpdateLane(fiber, suspenseConfig);
const update = createUpdate(eventTime, lane, suspenseConfig);
// 赋值tag为ForceUpdate
update.tag = ForceUpdate;
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
enqueueUpdate(fiber, update);
scheduleUpdateOnFiber(fiber, lane, eventTime);
},
};
你可以在这里看到
enqueueForceUpdate
代码
那么赋值update.tag = ForceUpdate;
有何作用呢?
在判断ClassComponent
是否需要更新时有两个条件需要满足:
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
你可以在这里看到这段代码
checkHasForceUpdateAfterProcessing:内部会判断本次更新的
Update
是否为ForceUpdate
。即如果本次更新的Update
中存在tag
为ForceUpdate
,则返回true
。checkShouldComponentUpdate:内部会调用
shouldComponentUpdate
方法。以及当该ClassComponent
为PureComponent
时会浅比较state
与props
。
你可以在这里看到
checkShouldComponentUpdate
代码
所以,当某次更新含有tag
为ForceUpdate
的Update
,那么当前ClassComponent
不会受其他性能优化手段
(shouldComponentUpdate
|PureComponent
)影响,一定会更新。
# 总结
至此,我们学习完了HostRoot | ClassComponent
所使用的Update
的更新流程。
在下一章我们会学习另一种数据结构的Update
—— 用于Hooks
的Update
。