packages/react/ReactBaseClasses.js 解析

这一篇是解析packages/react/ReactBaseClasses.js的源码的

像文件名说的那样,这个文件主要定义了Component、PureComponent 这两个基础类;

Component

Component类主要实现了以下两个原型链的方法:setStateforceUpdate,这两个方法的背后是基于updater去实现的(如果没有正确实例化并被挂载时会用ReactNoopUpdateQueue去实现);
ReactNoopUpdateQueue的处理行为就是针对enqueueSetStateenqueueForceUpdate去给出警告,告诉开发者,这里可能会有潜在的bug
以下是他们的源代码:

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');
};
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

然后比较关键的处理行为:
在开发模式下会针对两个deprecatedAPIs:isMountedreplaceState去做get时候的警告:

if (__DEV__) {
  const deprecatedAPIs = {
    isMounted: [
      'isMounted',
      'Instead, make sure to clean up subscriptions and pending requests in ' +
        'componentWillUnmount to prevent memory leaks.',
    ],
    replaceState: [
      'replaceState',
      'Refactor your code to use setState instead (see ' +
        'https://github.com/facebook/react/issues/3236).',
    ],
  };
  const defineDeprecationWarning = function(methodName, info) {
    Object.defineProperty(Component.prototype, methodName, {
      get: function() {
        lowPriorityWarning(
          false,
          '%s(...) is deprecated in plain JavaScript React classes. %s',
          info[0],
          info[1],
        );
        return undefined;
      },
    });
  };
  for (const fnName in deprecatedAPIs) {
    if (deprecatedAPIs.hasOwnProperty(fnName)) {
      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
    }
  }
}

PureComponent基类的实现

PureComponent的实现是通过ComponentDummy这个中间类去实现的;
ComponentDummy的作用就是断开对于Component.prototype的引用,这样在修改PureComponent的原型链方法的时候不会对Component造成影响,同时为了避免原型链的跳跃,做了一个Object.assign(pureComponentPrototype, Component.prototype);的处理。

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

/**
 * Convenience component with default shallow equality check for sCU.
 */
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;
}

const pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());
pureComponentPrototype.constructor = PureComponent;
// Avoid an extra prototype jump for these methods.
Object.assign(pureComponentPrototype, Component.prototype);
pureComponentPrototype.isPureReactComponent = true;

你可能感兴趣的:(packages/react/ReactBaseClasses.js 解析)