ZHANGYU.dev

October 14, 2023

React 类组件源码浅析

React24.7 min to read

虽然现在都是使用函数组件,但是类组件还是有函数组件无法替代的地方,比如一些独有的生命周期、很方便的存一些变量而不需要一大堆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(也就是setStateforceUpdate等),初始化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方法会对类实例的propsstate赋值,并初始化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

// 执行updateQueueexport 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);  },};

setStateforceUpdate主要区别是Updatetag类型不同,在执行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上,同时会维护某些情况下updateQueuebaseState值。

// ...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,但是会判断propsstate有没有变化。

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阶段

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

componentDidMountcomponentDidMount在同一个函数中执行,通过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来实现对应功能。