ReactComponent源码

ReactComponent模块,作为父类,创建基本的组件,内部实现setState、forceUpdate方法,用于更新state属性,重绘组件。

'use strict';

var _prodInvariant = require('./reactProdInvariant');// 生产环境React形式带url报错

// 组件尚未获得参数updater,即"react-dom"包下的"ReactUpdateQueue",调用setState、replaceState、forceUpdate时警告
var ReactNoopUpdateQueue = require('./ReactNoopUpdateQueue');

// 判断Object.defineProperty方法是否存在
var canDefineProperty = require('./canDefineProperty');

var emptyObject = require('fbjs/lib/emptyObject');

// invariant(condition,format,a,b,c,d,e,f) condition为否值,替换format中的"%s",并throw error报错
var invariant = require('fbjs/lib/invariant');

// warning(condition,format) condition为否值,替换format中的"%s",并console.error警告  
var warning = require('fbjs/lib/warning');

function ReactComponent(props, context, updater) {
  this.props = props;
  this.context = context;
  this.refs = emptyObject;
  
  // 组件实例化时将this.updater赋值为"react-dom"包下的"ReactUpdateQueue",用于实现setState、replaceState、forceUpdate方法
  this.updater = updater || ReactNoopUpdateQueue;
}

ReactComponent.prototype.isReactComponent = {};

// 通过调用ReactUpdateQueue.enqueueSetState、ReactUpdates.enqueueUpdate方法更新组件的state,及重绘组件,执行回调
ReactComponent.prototype.setState = function (partialState, callback) {
  !(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'setState');
  }
};


// 通过调用ReactUpdateQueue.enqueueForceUpdate、ReactUpdates.enqueueUpdate方法重绘组件,执行回调
ReactComponent.prototype.forceUpdate = function (callback) {
  this.updater.enqueueForceUpdate(this);
  if (callback) {
    this.updater.enqueueCallback(this, callback, 'forceUpdate');
  }
};

// 移除的方法
if (process.env.NODE_ENV !== 'production') {
  var 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).']
  };
  var defineDeprecationWarning = function (methodName, info) {
    if (canDefineProperty) {
      Object.defineProperty(ReactComponent.prototype, methodName, {
        get: function () {
          process.env.NODE_ENV !== 'production' ? 
            warning(false, '%s(...) is deprecated in plain JavaScript React classes. %s', info[0], info[1]) 
            : void 0;
          return undefined;
        }
      });
    }
  };
  for (var fnName in deprecatedAPIs) {
    if (deprecatedAPIs.hasOwnProperty(fnName)) {
      defineDeprecationWarning(fnName, deprecatedAPIs[fnName]);
    }
  }
}

module.exports = ReactComponent;