Skip to content
目录

Component 和 PureComponent做了啥?

不知道你有没有好奇过,平时我们在写Class组件的时候,比如this.setState, this.refs是怎么来的? 为什么Class组件需要继承Component或PureComponent呢?接下来,就从源代码的层面分析一下具体的实现

Component

可以看到,Component就几个属性:

  • props
  • context
  • refs
  • updater 更新状态的关键,正常情况下不直接使用
  • setState 更新状态的api, 底层调用的updater.enqueueSetState
  • forceUpdate 强制更新状态的api, 底层调用的updater.enqueueForceUpdate
javascript
function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}
Component.prototype.isReactComponent = {};
Component.prototype.setState = function(partialState, callback) {
  this.updater.enqueueSetState(this, partialState, callback, 'setState');
};

Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

PureComponent

可以看到,PureComponent继承了Component组件上的原型方法,额外增加了一个isPureReactComponent 属性,在更新节点会判断此值是否是true,如果是的话,会针对state和props做一个浅比较,再决定是否重新 渲染当前组件

// TODO 将isPureReactComponent作用的地方关联上

javascript
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}
// 原型继承
PureComponent.prototype = new ComponentDummy()
const pureComponentPrototype = PureComponent.prototype
pureComponentPrototype.constructor = PureComponent;
Object.assign(pureComponentPrototype, Component.prototype);
// PureComponent和Component区别的关键所在
pureComponentPrototype.isPureReactComponent = true;

updater

updater做的事情就是触发react的更新,具体的过程如下:

  1. 从当前组件实例上拿到对应的Fiber对象
  2. 计算当前触发的更新的一个过期时间戳 也就是优先级的意思
  3. 创建一个update对象
  4. 将update对象添加到当前Fiber的updateQueue上
  5. 执行一个更新的调度
typescript
const classComponentUpdater = {
  enqueueSetState(inst, payload, callback) {
    // 从当前组件实例上拿到对应的Fiber对象
    const fiber = getInstance(inst);
    const currentTime = requestCurrentTime();
    // 计算当前触发的更新的一个过期时间戳 也就是优先级的意思 
    const expirationTime = computeExpirationForFiber(currentTime, fiber);
    // 创建一个update对象
    const update = createUpdate(expirationTime);
    update.payload = payload;
    if (callback !== undefined && callback !== null) {
      update.callback = callback;
    }
    // 将update对象添加到当前Fiber的updateQueue上
    enqueueUpdate(fiber, update);
    // 执行一个更新的调度
    scheduleWork(fiber, expirationTime);
  },
  enqueueForceUpdate(inst, callback) {
    const fiber = getInstance(inst);
    const currentTime = requestCurrentTime();
    const expirationTime = computeExpirationForFiber(currentTime, fiber);
    const update = createUpdate(expirationTime);
    // 标记当前update是一个强制更新
    update.tag = ForceUpdate;
    if (callback !== undefined && callback !== null) {
      update.callback = callback;
    }
    enqueueUpdate(fiber, update);
    scheduleWork(fiber, expirationTime);
  },
};

TIP

在实例化class组件的时候, 并没有传递updater参数, 而是在实例化之后,在立即设置updater的

备案号: 浙ICP备2023000081号