Appearance
ClassComponent 组件
对于 Class 类型的组件, 在 beginWork 中,主要做了以下工作:
- 将组件的 FiberNode 节点转换成对应的 Dom 节点,并存放到
fiber.stateNode中 - 处理 Class 组件生命周期函数
- 处理组件的 Context 上下文
updateClassComponent 函数
处理组件的上下文 context
- 处理旧版上下文逻辑
getChildContext prepareToReadContext方法为处理上下文进行准备工作- 在
constructClassInstance方法中,根据以下优先级去处理上下文的值- 是否存在 contextType 对象,存在则通过
readContext方法读取 context 对象 - 是否存在 contextTypes 对象,存在则通过
getMaskedContext方法读取 context 对象 - 以上都不存在,则返回空对象
- 是否存在 contextType 对象,存在则通过
js
function updateClassComponent(
current: Fiber | null,
workInProgress: Fiber,
Component: any,
nextProps: any,
renderLanes: Lanes
) {
// Push context providers early to prevent context stack mismatches.
// During mounting we don't know the child context yet as the instance doesn't exist.
// We will invalidate the child context in finishClassComponent() right after rendering.
let hasContext;
if (isLegacyContextProvider(Component)) {
hasContext = true;
pushLegacyContextProvider(workInProgress);
} else {
hasContext = false;
}
prepareToReadContext(workInProgress, renderLanes);
return nextUnitOfWork;
}
function constructClassInstance(
workInProgress: Fiber,
ctor: any,
props: any
): any {
let isLegacyContextConsumer = false;
let unmaskedContext = emptyContextObject;
let context = emptyContextObject;
// 获取 class 对象上的 contextType 属性
const contextType = ctor.contextType;
// 1. 获取初始化的时候传入的 context 值
if (typeof contextType === "object" && contextType !== null) {
// 读取 Class.contextType 传入的 context 对象
context = readContext((contextType: any));
} else if (!disableLegacyContext) {
//
unmaskedContext = getUnmaskedContext(workInProgress, ctor, true);
const contextTypes = ctor.contextTypes;
isLegacyContextConsumer =
contextTypes !== null && contextTypes !== undefined;
context = isLegacyContextConsumer
? getMaskedContext(workInProgress, unmaskedContext)
: emptyContextObject;
}
// Cache unmasked context so we can avoid recreating masked context unless necessary.
// ReactFiberContext usually updates this cache but can't for newly-created instances.
if (isLegacyContextConsumer) {
cacheContext(workInProgress, unmaskedContext, context);
}
return instance;
}首次渲染
判断条件
js
instance === null;执行逻辑
constructClassInstance(workInProgress, Component, nextProps)
- 处理 Class 组件的 context 值
- 执行 Class 组件的 constructor 方法
根据第一步处理好的 context 的值,执行 Class 组件的 constructor 方法,创建 Class 组件的实例。
js
// 执行 Class 的 constructor 方法, 并传入 props 和 context
let instance = new ctor(props, context);- 处理
FiberNode.stateNode和instace._reactInternal的关联关系
主要是修改以下几个属性的指向
FiberNode.stateNode === instace, 指向 Class 组件的实例对象 instanceinstance._reactInternals === FiberNode,Class 组件的实例对象指向 FiberNode
js
/**
* 修改FiberNode的几个属性
* - 修改 stateNode 指向 Class 组件的实例对象 instance
* - 修改FiberNode.stateNode._reactInternals 指向 FiberNode
* - 修改FiberNode.stateNode.updater 指向 classComponentUpdater
* @param {*} workInProgress
* @param {*} instance
*/
function adoptClassInstance(workInProgress: Fiber, instance: any): void {
instance.updater = classComponentUpdater;
// 将 FiberNode.stateNode 指向实例对象
workInProgress.stateNode = instance;
// The instance needs access to the fiber so that it can schedule updates
// 将 Class 组件的实例对象 和 FiberNode._reactInternals 关联起来
setInstance(instance, workInProgress);
if (__DEV__) {
instance._reactInternalInstance = fakeInternalInstance;
}
}- 缓存 context 对象到
instance.**reactInternalMemoizedUnmaskedChildContext和instance.__reactInternalMemoizedMaskedChildContext
mountClassInstance(workInProgress, Component, nextProps, renderLanes)
执行 Class 组件的 FiberNode 到 dom 的生命周期函数
- 执行
getDerivedStateFromProps方法
从 Props 中获得 State,所以该函数的功能就是从更新后的 props 中获取 State,它让组件在 props 发生改变时更新它自身的内部 state。
- 执行
componentWillMount生命周期方法
js
/**
* 调用 Class 组件的 componentWillMount 方法 和 unsafe_componentWillMount 方法
* 根据返回的新旧 state 是否发生了变化, 决定是否需要重新渲染组件
* 如果发生了变化, 则执行 classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
* @param {*} workInProgress
* @param {*} instance
*/
function callComponentWillMount(workInProgress, instance) {
// 缓存 componentWillMount 执行之前 state 的值
const oldState = instance.state;
if (typeof instance.componentWillMount === "function") {
instance.componentWillMount();
}
if (typeof instance.UNSAFE_componentWillMount === "function") {
instance.UNSAFE_componentWillMount();
}
// 如果 state 发生了变化, 则将 state 重新赋值给 instance.state
if (oldState !== instance.state) {
classComponentUpdater.enqueueReplaceState(instance, instance.state, null);
}
}enqueueReplaceState
在 Class 组件首次渲染的时候,
