react源码之ReactBaseClasses.js

471 阅读2分钟

ReactBaseClasses.js

该文件声明了Component和PureComponent

Component

/**
 * Base class helpers for the updating state of a component.
 */
function Component(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  this.updater = updater || ReactNoopUpdateQueue;
}

setState

 * @param {object|function} partialState Next partial state or function to
 *        produce next partial state to be merged with current state.
 * @param {?function} callback Called after state is updated.
 * @final
 * @protected
 */
Component.prototype.setState = function(partialState, callback) {
  invariant(
    typeof partialState === 'object' ||
      typeof partialState === 'function' ||
      partialState == null,
    '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');
};

第一个参数必须是对象、函数或者null,否则执行invariant就会报错。 第二个参数是state更新之后的回调函数。

  • 不能确保当前的组件的state立刻更新,所以紧接着使用的state可能是旧值。
  • 不能确保setState是同步的,可能是之后统一调用的,想要使用更新后的state的解决方式是提供更新后的回调函数。
  • 当提供一个函数fn给setState时,fn将在之后的某个时刻被调用(异步)。 fn将与最新的 组件参数一起调用(state, props, context)。 这些参数(state, props, context)可能与this.*不同,因为fn可能在receiveProps之后但shouldComponentUpdate生命周期之前被调用,新的state, props, context还没有分配到this(当前组件)上。

forceUpdate

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

callback是强制更新之后的后调

  • forceUpdate可以强制唤起组件更新流程
  • shouldComponentUpdate生命周期不再调用,componentWillUpdate和componentDidUpdate依旧有效

PureComponent

PureComponent的实现的理解请看注释,如有错误,还望指正!

function ComponentDummy() {}
// 继承Component的原型
ComponentDummy.prototype = Component.prototype;

function PureComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  // If a component has string refs, we will assign a different object later.
  this.refs = emptyObject;
  this.updater = updater || ReactNoopUpdateQueue;
}

/* pureComponentPrototype实际是PureComponent原型的地址,
并初始化PureComponent的原型为ComponentDummy的一个实例,
因为ComponentDummy的原型就是Component的原型,
因此间接使得PureComponent的原型的__proto__ 是Component的原型
(个人感觉是为了使得PureComponent instanceof Component结果为true)
*/
const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
// 使得PureComponent原型的constructor指向本身
pureComponentPrototype.constructor = PureComponent;
// PureComponent的原型中添加Component原型中的可枚举属性
// 目的是为了减少原型查找
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;