React 类组件源码浅析
Posted 小张的成长历程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React 类组件源码浅析相关的知识,希望对你有一定的参考价值。
虽然现在都是使用函数组件,但是类组件还是有函数组件无法替代的地方,比如一些独有的生命周期、很方便的存一些变量而不需要一大堆useRef
、实例的方法调用更方便。
以下源码浅析React版本为17.0.1。
类组件的Fiber节点的创建
类组件的Fiber节点由父级节点进入reconcileChildren
方法后通过createFiberFromTypeAndProps
方法创建,在这个方法中会通过prototype.isReactComponent
判断该节点是否为ClassComponent
。
export function createFiberFromTypeAndProps(
type: any, // React$ElementType
key: null | string,
pendingProps: any,
owner: null | Fiber,
mode: TypeOfMode,
lanes: Lanes,
): Fiber {
// 省略无关代码...
let fiberTag = IndeterminateComponent;
if (typeof type === 'function') {
// 通过prototype.isReactComponent判断是不是类组件
if (shouldConstruct(type)) {
// 标记为类组件
fiberTag = ClassComponent;
}
}
// 省略无关代码...
return fiber;
}
// 通过prototype.isReactComponent判断是不是类组件
function shouldConstruct(Component: Function) {
const prototype = Component.prototype;
return !!(prototype && prototype.isReactComponent);
}
由于类组件需要继承Component
,所有存在prototype.isReactComponent
,该节点被标记为类组件,后续会进入类组件的判断。
类组件实例的创建和更新
上一步标记了该Fiber节点为ClassComponent
,该节点进入beginWork
阶段时会通过判断进入updateClassComponent
方法。
// ...省略无关代码
case ClassComponent: {
// 类组件type是类的本身,不是类的实例
const Component = workInProgress.type;
const unresolvedProps = workInProgress.pendingProps;
// 合并defaultProps
const resolvedProps =
workInProgress.elementType === Component
? unresolvedProps
: resolveDefaultProps(Component, unresolvedProps);
return updateClassComponent(
current,
workInProgress,
Component,
resolvedProps,
renderLanes,
);
}
// ...省略无关代码
无论类组件是首次挂载还是更新,都会进入updateClassComponent
。
function updateClassComponent(
current: Fiber | null,
workInProgress: Fiber,
Component: any,
nextProps: any,
renderLanes: Lanes,
) {
// 省略无关代码...
// 类实例
const instance = workInProgress.stateNode;
let shouldUpdate;
// mount
if (instance === null) {
// 省略无关代码...
// 创建并初始化类实例
constructClassInstance(workInProgress, Component, nextProps);
mountClassInstance(workInProgress, Component, nextProps, renderLanes);
shouldUpdate = true;
} else if (current === null) {
// 中断后继续渲染...
} else {
// update
shouldUpdate = updateClassInstance(
current,
workInProgress,
Component,
nextProps,
renderLanes,
);
}
// 返回子Fiber节点
const nextUnitOfWork = finishClassComponent(
current,
workInProgress,
Component,
shouldUpdate,
hasContext,
renderLanes,
);
return nextUnitOfWork;
}
updateClassComponent
中会针对Mount和Update分开判断。
Mount时
Mount时会创建实例,赋值updater
(也就是setState
和forceUpdate
等),初始化updateQueue
。主要调用了constructClassInstance方法和
mountClassInstance`方法。
constructClassInstance
constructClassInstance
方法主要创建类实例并绑定到Fiber节点,赋值updater
。
function constructClassInstance(
workInProgress: Fiber,
ctor: any,
props: any,
): any {
let isLegacyContextConsumer = false;
let unmaskedContext = emptyContextObject;
let context = emptyContextObject;
// 省略context相关代码...
// 创建实例
const instance = new ctor(props, context);
// 将state赋值到fiber节点的memoizedState
const state = (workInProgress.memoizedState =
instance.state !== null && instance.state !== undefined
? instance.state
: null);
// 赋值updater
adoptClassInstance(workInProgress, instance);
// 省略无关代码...
return instance;
}
function adoptClassInstance(workInProgress: Fiber, instance: any): void {
// 赋值updater
instance.updater = classComponentUpdater;
workInProgress.stateNode = instance;
// 通过instance._reactInternals属性可以访问fiber节点
setInstance(instance, workInProgress);
}
mountClassInstance
mountClassInstance
方法会对类实例的props
、state
赋值,并初始化updateQueue
,同时执行getDerivedStateFromProps
生命周期获取新的state
,同时根据判断执行componentWillMount
生命周期。
后续state
的值会通过执行updateQueue
的中的update
来更新。
function mountClassInstance(
workInProgress: Fiber,
ctor: any,
newProps: any,
renderLanes: Lanes,
): void {
// 类实例
const instance = workInProgress.stateNode;
// 赋值props,state
instance.props = newProps;
instance.state = workInProgress.memoizedState;
instance.refs = emptyRefsObject;
// 初始化UpdateQueue
initializeUpdateQueue(workInProgress);
const contextType = ctor.contextType;
if (typeof contextType === 'object' && contextType !== null) {
// 把context挂在实例的context上
instance.context = readContext(contextType);
}
// 执行updateQueue计算新的state
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
instance.state = workInProgress.memoizedState;
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
// 执行getDerivedStateFromProps赋值给state
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
instance.state = workInProgress.memoizedState;
}
// 调用componentWillMount
if (
typeof ctor.getDerivedStateFromProps !== 'function' &&
typeof instance.getSnapshotBeforeUpdate !== 'function' &&
(typeof instance.UNSAFE_componentWillMount === 'function' ||
typeof instance.componentWillMount === 'function')
) {
// 调用UNSAFE_componentWillMount
callComponentWillMount(workInProgress, instance);
// 执行updateQueue处理UNSAFE_componentWillMount里发起的update
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
// 赋值新的state
instance.state = workInProgress.memoizedState;
}
// 有componentDidMount的情况下flags增加Update
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update;
}
}
Update时
Update时调用updateClassInstance
来处理更新。
updateClassInstance
function updateClassInstance(
current: Fiber,
workInProgress: Fiber,
ctor: any,
newProps: any,
renderLanes: Lanes,
): boolean {
// 类实例
const instance = workInProgress.stateNode;
// clone当前updateQueue到workInProgress
cloneUpdateQueue(current, workInProgress);
// 当fiber走完beginWork阶段,memoizedProps会被赋值为pendingProps
const unresolvedOldProps = workInProgress.memoizedProps;
const oldProps =
workInProgress.type === workInProgress.elementType
? unresolvedOldProps
: resolveDefaultProps(workInProgress.type, unresolvedOldProps);
instance.props = oldProps;
const unresolvedNewProps = workInProgress.pendingProps;
// context
const oldContext = instance.context;
const contextType = ctor.contextType;
let nextContext = emptyContextObject;
if (typeof contextType === 'object' && contextType !== null) {
nextContext = readContext(contextType);
} // ...
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
// 是否使用了新的生命周期
const hasNewLifecycles =
typeof getDerivedStateFromProps === 'function' ||
typeof instance.getSnapshotBeforeUpdate === 'function';
// 调用UNSAFE_componentWillReceiveProps
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillReceiveProps === 'function' ||
typeof instance.componentWillReceiveProps === 'function')
) {
if (
unresolvedOldProps !== unresolvedNewProps ||
oldContext !== nextContext
) {
callComponentWillReceiveProps(
workInProgress,
instance,
newProps,
nextContext,
);
}
}
// 执行updateQueue之前重置forceUpdate标识
resetHasForceUpdateBeforeProcessing();
const oldState = workInProgress.memoizedState;
let newState = (instance.state = oldState);
// 执行updateQueue获取新的state
processUpdateQueue(workInProgress, newProps, instance, renderLanes);
newState = workInProgress.memoizedState;
// 没看懂这段
if (
unresolvedOldProps === unresolvedNewProps &&
oldState === newState &&
!hasContextChanged() &&
!checkHasForceUpdateAfterProcessing()
) {
if (typeof instance.componentDidUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Update;
}
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
return false;
}
// 执行getDerivedStateFromProps
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
newState = workInProgress.memoizedState;
}
// 根据forceUpdate标识和shouldComponentUpdate执行结果判断是否需要更新
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
// 需要更新
if (shouldUpdate) {
// 调用UNSAFE_componentWillUpdate生命周期
if (
!hasNewLifecycles &&
(typeof instance.UNSAFE_componentWillUpdate === 'function' ||
typeof instance.componentWillUpdate === 'function')
) {
if (typeof instance.componentWillUpdate === 'function') {
instance.componentWillUpdate(newProps, newState, nextContext);
}
if (typeof instance.UNSAFE_componentWillUpdate === 'function') {
instance.UNSAFE_componentWillUpdate(newProps, newState, nextContext);
}
}
if (typeof instance.componentDidUpdate === 'function') {
workInProgress.flags |= Update;
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
workInProgress.flags |= Snapshot;
}
} else {
// 没看懂这段
if (typeof instance.componentDidUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Update;
}
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
workInProgress.memoizedProps = newProps;
workInProgress.memoizedState = newState;
}
// 更新实例的props,state,context
instance.props = newProps;
instance.state = newState;
instance.context = nextContext;
return shouldUpdate;
}
finishClassComponent
Mount和Update后都需要执行finishClassComponent
方法,该方法会返回经过reconcileChildren
处理后的child
节点。
function finishClassComponent(
current: Fiber | null,
workInProgress: Fiber,
Component: any,
shouldUpdate: boolean,
hasContext: boolean,
renderLanes: Lanes,
) {
// 标记需要赋值ref
markRef(current, workInProgress);
const didCaptureError = (workInProgress.flags & DidCapture) !== NoFlags;
// 不需要更新
if (!shouldUpdate && !didCaptureError) {
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
}
const instance = workInProgress.stateNode;
let nextChildren;
// 出错了并且getDerivedStateFromError没有声明
if (
didCaptureError &&
typeof Component.getDerivedStateFromError !== 'function'
) {
// 不渲染children,后续交给componentDidCatch处理
nextChildren = null;
} else {
// 执行render获取children
nextChildren = instance.render();
}
if (current !== null && didCaptureError) {
forceUnmountCurrentAndReconcile(
current,
workInProgress,
nextChildren,
renderLanes,
);
} else {
// 处理children
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
}
workInProgress.memoizedState = instance.state;
return workInProgress.child;
}
类组件的更新调度
类的更新存在于Fiber节点上的updateQueue
,上面存储了Update
的信息,类组件可以通过setState
创建Update
并添加到updateQueue
发起更新调度,在Update时执行updateClassInstance
方法时会调用processUpdateQueue
方法计算新的state
。
UpdateQueue和Update的结构
在类组件Mount时执行mountClassInstance
方法时,内部会调用initializeUpdateQueue
方法初始化updateQueue
。
export function initializeUpdateQueue<State>(fiber: Fiber): void {
const queue: UpdateQueue<State> = {
baseState: fiber.memoizedState, // update基于baseState计算新的state
firstBaseUpdate: null, // 优先级相关,被跳过的update
lastBaseUpdate: null, // 优先级相关,被跳过的update
shared: {
pending: null, // 当前更新的update链表
},
effects: null, // update的callback,对应setState第二个参数
};
fiber.updateQueue = queue; // 初始化
}
通过执行setState
会调用createUpdate
方法创建update
,并添加到updateQueue
中,Update
是一个环形链表,next
字段指向下一个Update
。
export function createUpdate(eventTime: number, lane: Lane): Update<*> {
const update: Update<*> = {
eventTime,
lane, // 优先级相关
tag: UpdateState, // 根据tag判断更新state值
payload: null, // 对应setState的第一个参数
callback: null, // 对应setState的第二个参数
next: null, // 由于是链表结构,指向下一个update
};
return update;
}
processUpdateQueue
在类组件Update时会调用processUpdateQueue
方法中会执行updateQueue
来获得新的state
。
// 执行updateQueue
export function processUpdateQueue<State>(
workInProgress: Fiber,
props: any,
instance: any,
renderLanes: Lanes,
): void {
// ClassComponent中总是不为null
const queue: UpdateQueue<State> = (workInProgress.updateQueue: any);
// 全局标识判断是不是通过forceUpdate发起的更新
hasForceUpdate = false;
// 由于优先级在上次更新被跳过的update链表
let firstBaseUpdate = queue.firstBaseUpdate;
let lastBaseUpdate = queue.lastBaseUpdate;
// 如果本次更新有pending updates,就拼接到baseUpdate
let pendingQueue = queue.shared.pending;
if (pendingQueue !== null) {
queue.shared.pending = null;
// 断开最后一个和第一个的连接,这样pendingQueue就不是环状了
const lastPendingUpdate = pendingQueue;
const firstPendingUpdate = lastPendingUpdate.next;
lastPendingUpdate.next = null;
// 把pending updates连接到base queue
if (lastBaseUpdate === null) {
firstBaseUpdate = firstPendingUpdate;
} else {
lastBaseUpdate.next = firstPendingUpdate;
}
lastBaseUpdate = lastPendingUpdate;
// 保证current和workInProgress一致
const current = workInProgress.alternate;
if (current !== null) {
// 省略代码...
}
}
if (firstBaseUpdate !== null) {
let newState = queue.baseState;
let newLanes = NoLanes;
let newBaseState = null;
let newFirstBaseUpdate = null;
let newLastBaseUpdate = null;
let update = firstBaseUpdate;
do {
const updateLane = update.lane;
const updateEventTime = update.eventTime;
// 优先级不够的任务
if (!isSubsetOfLanes(renderLanes, updateLane)) {
// clone跳过的Update
const clone: Update<State> = {
eventTime: updateEventTime,
lane: updateLane,
tag: update.tag,
payload: update.payload,
callback: update.callback,
next: null,
};
// 连接到firstBaseUpdate或lastBaseUpdate
if (newLastBaseUpdate === null) {
newFirstBaseUpdate = newLastBaseUpdate = clone;
// 有跳过的Update下次以此时的state值计算
newBaseState = newState;
} else {
newLastBaseUpdate = newLastBaseUpdate.next = clone;
}
newLanes = mergeLanes(newLanes, updateLane);
} else {
// 优先级够不会被跳过的Update
// 如果之前有被跳过的update,为了保证下次更新的连续性,也需要添加进laseBaseUpdate
if (newLastBaseUpdate !== null) {
const clone: Update<State> = {
eventTime: updateEventTime,
// NoLane在下次执行时不会被上面优先级不够跳过
lane: NoLane,
tag: update.tag,
payload: update.payload,
callback: update.callback,
next: null,
};
newLastBaseUpdate = newLastBaseUpdate.next = clone;
}
// 根据update计算新的state
newState = getStateFromUpdate(
workInProgress,
queue,
update,
newState,
props,
instance,
);
const callback = update.callback;
// 回调函数push进effects数组
if (callback !== null) {
workInProgress.flags |= Callback;
const effects = queue.effects;
if (effects === null) {
queue.effects = [update];
} else {
effects.push(update);
}
}
}
// 下一个update
update = update.next;
if (update === null) {
pendingQueue = queue.shared.pending;
if (pendingQueue === null) {
break;
} else {
// setState函数里又调用了setState会进入这个判断
const lastPendingUpdate = pendingQueue;
const firstPendingUpdate = ((lastPendingUpdate.next: any): Update<State>);
lastPendingUpdate.next = null;
update = firstPendingUpdate;
queue.lastBaseUpdate = lastPendingUpdate;
queue.shared.pending = null;
}
}
} while (true);
if (newLastBaseUpdate === null) {
newBaseState = newState;
}
queue.baseState = ((newBaseState: any): State);
queue.firstBaseUpdate = newFirstBaseUpdate;
queue.lastBaseUpdate = newLastBaseUpdate;
markSkippedUpdateLanes(newLanes);
workInProgress.lanes = newLanes;
workInProgress.memoizedState = newState; // 反应到页面的state值
}
}
processUpdateQueue
方法里会执行updateQueue
计算新的state
值,主要是其中包含了优先级以及跳过的Update
的判断有一些障目。主要逻辑还是循环Update
链表来获得新的state
。
state
值会通过getStateFromUpdate
方法来获得。
getStateFromUpdate
getStateFromUpdate
函数内会根据Update
类型来处理state
,这里主要关注由setState
发起的UpdateState
类型。
function getStateFromUpdate<State>(
workInProgress: Fiber,
queue: UpdateQueue<State>,
update: Update<State>,
prevState: State,
nextProps: any,
instance: any,
): any {
switch (update.tag) {
// 省略代码...
// tag为UpdateState
case UpdateState: {
const payload = update.payload;
let partialState;
if (typeof payload === 'function') {
// 当第一个参数是函数时
partialState = payload.call(instance, prevState, nextProps);
} else {
// 第一个参数是对象
partialState = payload;
}
if (partialState === null || partialState === undefined) {
return prevState;
}
// 合并state
return Object.assign({}, prevState, partialState);
},
// tag为ForceUpdate
case ForceUpdate: {
hasForceUpdate = true;
return prevState;
}
}
return prevState;
}
setState和forceUpdate
setState
方法和forceUpdate
方法是继承Component
后原型链上的方法,本质是调用的在Mount时赋值当this.updater
。
Component.prototype.setState = function(partialState, callback) {
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
Component.prototype.forceUpdate = function(callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};
而this.updater
是在Mount时在constructClassInstance
方法里调用adoptClassInstance
方法时赋值的。
// adoptClassInstance...
instance.updater = classComponentUpdater;
// 通过instance._reactInternals属性可以访问fiber节点
setInstance(instance, workInProgress);
classComponentUpdater
updater
本质调用的就是classComponentUpdater
的方法。
const classComponentUpdater = {
enqueueSetState(inst, payload, callback) {
// 从实例的_reactInternals属性取出fiber节点
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber);
// 创建update
const update = createUpdate(eventTime, lane);
update.payload = payload;
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
// Update入队
enqueueUpdate(fiber, update);
// 发起更新调度
scheduleUpdateOnFiber(fiber, lane, eventTime);
},
enqueueForceUpdate(inst, callback) {
const fiber = getInstance(inst);
const eventTime = requestEventTime();
const lane = requestUpdateLane(fiber);
const update = createUpdate(eventTime, lane);
update.tag = ForceUpdate;
if (callback !== undefined && callback !== null) {
update.callback = callback;
}
enqueueUpdate(fiber, update);
scheduleUpdateOnFiber(fiber, lane, eventTime);
},
};
setState
和forceUpdate
主要区别是Update
的tag
类型不同,在执行updateQueue
通过Update
获取state
时,getStateFromUpdate
方法返回不同的结果。
它们的回调函数会在后续的commit阶段执行。
类组件生命周期的执行
以下生命周期不包含未来不推荐使用的UNSAFE
生命周期,省略了部分无关代码。
render阶段
在未来开启concurrent
模式后,目前UNSAFE
的生命周期可能会因为渲染中断或优先级的高低执行多次,虽然目前不会有任何问题,但还是应该尽量避免使用。
constructor
constructor
在执行的时候实际上会传入context
作为第二个参数,这个在文档上是没有的。
function constructClassInstance(
// ...
): any {
// 创建实例
const instance = new ctor(props, context);
}
shouldComponentUpdate
shouldComponentUpdate
在Update时通过updateClassInstance
方法里每次都会调用。
function updateClassInstance(
// ...
): boolean {
const shouldUpdate =
checkHasForceUpdateAfterProcessing() ||
// 调用shouldComponentUpdate
checkShouldComponentUpdate(
workInProgress,
ctor,
oldProps,
newProps,
oldState,
newState,
nextContext,
);
}
getDerivedStateFromProps
getDerivedStateFromProps
就像文档写的***会在每次渲染前触发此方法***,它在Mount时和Update时都会调用,通过执行函数获取一个新的state
值,并且会合并到当前state
上,同时会维护某些情况下updateQueue
的baseState
值。
// ...
const getDerivedStateFromProps = ctor.getDerivedStateFromProps;
if (typeof getDerivedStateFromProps === 'function') {
applyDerivedStateFromProps(
workInProgress,
ctor,
getDerivedStateFromProps,
newProps,
);
// 赋值给
instance.state = workInProgress.memoizedState;
}
componentDidMount
虽然在render阶段不会执行componentDidMount
,但是它会在render
阶段打上flags
,后续commit
阶段才会执行。
function mountClassInstance(
// ...
): void {
// 有componentDidMount的情况下flags增加Update
if (typeof instance.componentDidMount === 'function') {
workInProgress.flags |= Update;
}
}
componentDidMount和getSnapshotBeforeUpdate
和componentDidMount
相同,在render
阶段需要打上flags
,但是会判断props
和state
有没有变化。
function updateClassInstance(
// ...
): boolean {
if (typeof instance.componentDidUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Update;
}
}
if (typeof instance.getSnapshotBeforeUpdate === 'function') {
if (
unresolvedOldProps !== current.memoizedProps ||
oldState !== current.memoizedState
) {
workInProgress.flags |= Snapshot;
}
}
}
commit阶段
commit阶段又分为3个阶段
-
BeforeMutation阶段 -
Mutation阶段 -
Layout阶段
BeforeMutation阶段
BeforeMutation阶段在操作DOM前。
getSnapshotBeforeUpdate
通过current
判断是否为Update时,并执行getSnapshotBeforeUpdate
方法,按照文档的描述,这个生命周期可以做滚动条的位置,因为这时候获取DOM的值还是旧的。
function commitBeforeMutationLifeCycles(
current: Fiber | null,
finishedWork: Fiber,
): void {
switch (finishedWork.tag) {
// ...
case ClassComponent: {
// 判断flags有Snapshot,在render阶段会打上flags
if (finishedWork.flags & Snapshot) {
// 通过current判断当前为Mount还是Update
if (current !== null) {
const prevProps = current.memoizedProps;
const prevState = current.memoizedState;
const instance = finishedWork.stateNode;
const snapshot = instance.getSnapshotBeforeUpdate(
finishedWork.elementType === finishedWork.type
? prevProps
: resolveDefaultProps(finishedWork.type, prevProps),
prevState,
);
// 返回值是存在一个内部变量里的
instance.__reactInternalSnapshotBeforeUpdate = snapshot;
}
}
return;
}
// ...
}
}
Mutation阶段
Mution阶段正在对DOM进行操作。
componentWillUnMount
当Fiber节点flags
包含Deletion
时,最后会进入commitUnmount
方法,由safelyCallComponentWillUnmount
方法调用componentWillUnMount
。
function commitUnmount(
finishedRoot: FiberRoot,
current: Fiber,
renderPriorityLevel: ReactPriorityLevel,
): void {
switch (current.tag) {
// ...
case ClassComponent: {
safelyDetachRef(current);
const instance = current.stateNode;
if (typeof instance.componentWillUnmount === 'function') {
safelyCallComponentWillUnmount(current, instance);
}
return;
}
// ...
}
}
Layout阶段
Layou阶段是操作DOM后。
componentDidMount和componentDidMount
componentDidMount
和componentDidMount
在同一个函数中执行,通过current === null
判断是Mount还是Update来确定执行哪一个函数。
function commitLifeCycles(
finishedRoot: FiberRoot,
current: Fiber | null,
finishedWork: Fiber,
committedLanes: Lanes,
): void {
switch (finishedWork.tag) {
case ClassComponent: {
const instance = finishedWork.stateNode;
if (finishedWork.flags & Update) {
// mount时
if (current === null) {
// 执行componentDidMount
instance.componentDidMount();
} else {
// update时,从current Fiber节点取出之前的props和state
const prevProps =
finishedWork.elementType === finishedWork.type
? current.memoizedProps
: resolveDefaultProps(finishedWork.type, current.memoizedProps);
const prevState = current.memoizedState;
instance.componentDidUpdate(
prevProps,
prevState,
instance.__reactInternalSnapshotBeforeUpdate,
);
}
}
// 这里会执行updateQueue上的effects,其中存的是setState和forceUpdate的callback
const updateQueue: UpdateQueue<
*,
> | null = (finishedWork.updateQueue: any);
if (updateQueue !== null) {
commitUpdateQueue(finishedWork, updateQueue, instance);
}
return;
}
}
}
总结
以上简单从源码简单分析了类组件Fiber节点创建、类组件实例创建、更新,发起更新调度,生命周期的执行,回头再对比Hooks,我觉得某些情况类组件真的还挺方便,虽然大部分功能函数组件都能实现,但是还是的花一些时间使用Hooks来实现对应功能。
以上是关于React 类组件源码浅析的主要内容,如果未能解决你的问题,请参考以下文章