React 源码阅读-10

ReactBaseClasses.png

ReactBaseClasses

这个文件是export出了Component, PureComponent

export {Component, PureComponent};

源码+注释

/**
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

//生产环境使用,为了抛出错误信息
import invariant from 'shared/invariant';

//只在开发环境有效,使用 console.warn(message);
import lowPriorityWarning from 'shared/lowPriorityWarning';

//没有传入参数updater参数时,this.updater的值就是ReactNoopUpdateQueue
//用于报警告的 可以忽略
import ReactNoopUpdateQueue from './ReactNoopUpdateQueue';

const emptyObject = {};
if (__DEV__) {
  Object.freeze(emptyObject);
  // Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象
}

/**
 * Base class helpers for the updating state of a component.
 */

// Base class用于更新组件的state。\
// 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.
  // 如果组件ref具有字符串引用,稍后将分配一个不同的对象
  this.refs = emptyObject;
  // We initialize the default updater but the real one gets injected by the
  // renderer.
  // 我们初始化默认的更新程序,但是真正的更新程序会被渲染
  this.updater = updater || ReactNoopUpdateQueue;
}

Component.prototype.isReactComponent = {};

/**
 *不能保证`this.state`会立即更新,因此
 *调用此方法后访问`this.state`可能会返回旧值。
 *
 *不能保证对setState的调用将同步运行,
 *因为它们最终可能会一起批处理。您可以提供可选
 *实际调用setState时将执行的回调
 *完成。
 *
 *将函数提供给setState时,它将在以下时间点被调用
 *未来(不同步)。它将被称为最新
 *组件参数(状态,道具,上下文)。这些值可以不同
 *from this。*因为您的函数可能在receiveProps之后但之前被调用
 *shouldComponentUpdate,这个新的状态,道具和上下文还没有
 *分配给这个
 *
 * @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');
};

/**
强制更新。仅当已知时才应调用此方法
 *确定我们不是DOM事务中的**。
 *
 *如果您知道
 *组件的状态已更改,但未调用`setState`。
 *
 *这不会调用`shouldComponentUpdate`,但是会调用
 *componentWillUpdate和componentDidUpdate。
 *
 * @param {?function} callback Called after update is complete.
 * @final
 * @protected
 */
Component.prototype.forceUpdate = function(callback) {
  this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};

/**
不推荐使用的API。这些API曾经存在于经典的React类上,但是由于
 *我们要弃用它们,我们不会将它们移至此
 *现代基层。取而代之的是,我们定义了一个getter,如果它被访问,它会发出警告
 已经废弃
 */
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]);
    }
  }
}

//虚拟组件
function ComponentDummy() {}
ComponentDummy.prototype = Component.prototype;

// 带有默认浅层相等性检查的便利组件。
/**
 * Convenience component with default shallow equality check for sCU.
 */
// PureComponent最佳情况是展示组件
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());
// PureComponent.prototype等于ComponentDummy的实例 只继承Component的原型,不包括constructor,以此来节省内存。
pureComponentPrototype.constructor = PureComponent;
// 原型的constructor等于自身,覆盖掉Component.prototype的constructor(Component)
// Avoid an extra prototype jump for these methods.
// 对于这些方法,请避免额外的原型跳转 为了减少一次原型链查找
Object.assign(pureComponentPrototype, Component.prototype);

pureComponentPrototype.isPureReactComponent = true;

// PureComponent是自带了一个简单的shouldComponentUpdate来优化更新机制的

export {Component, PureComponent};
https://juejin.im/post/5b614d...

https://segmentfault.com/a/11...


xiaoping
337 声望12 粉丝

保持学习,记一下自己的学习经历