美文网首页React让前端飞React Native开发
阅读react源码:(一).组件的实例化,元素挂载,重绘rend

阅读react源码:(一).组件的实例化,元素挂载,重绘rend

作者: Evan_zhan | 来源:发表于2018-01-14 18:04 被阅读263次

    react版本:
    15.6-dev
    文件名:
    ReactCompositeComponent.js
    路径:
    react/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
    github地址:
    https://github.com/facebook/react/blob/15.6-dev/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js

    源码(ReactCompositeComponent.js)

    'use strict';  
      
    var _prodInvariant = require('./reactProdInvariant'),// 生产环境React形式带url报错   
        _assign = require('object-assign');  
      
    var React = require('react/lib/React');  
      
    // 提供ReactComponentEnvironment.replaceNodeWithMarkup方法,用于替换挂载的Dom元素  
    var ReactComponentEnvironment = require('./ReactComponentEnvironment');  
      
    // 开发环境下,ReactClass组件被实例化或其render方法被调用时,向ReactCurrentOwner.current添加当前实例this  
    // 实例化完成或render方法执行完成,ReactCurrentOwner.current置为null  
    var ReactCurrentOwner = require('react/lib/ReactCurrentOwner');  
      
    // 调试用  
    var ReactErrorUtils = require('./ReactErrorUtils');  
      
    // 以对象形式存储组件实例  
    var ReactInstanceMap = require('./ReactInstanceMap');  
      
    // 调试用  
    var ReactInstrumentation = require('./ReactInstrumentation');  
      
    // 用于判断节点类型,ReactComponentElement元素返回1;ReactDomElement元素返回0;若为空,返回2  
    var ReactNodeTypes = require('./ReactNodeTypes');  
      
    // 用于挂载、移除、更新组件实例,作为方法的发起者,如ReactReconciler.mountComponent  
    var ReactReconciler = require('./ReactReconciler');  
      
    if (process.env.NODE_ENV !== 'production') {  
      var checkReactTypeSpec = require('./checkReactTypeSpec');  
    }  
      
    // 空对象,并且用Object.freeze冻结为不可修改、不可扩展  
    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');  
      
    // shallowEqual(A,B)比较值相等,及浅比较键值相等  
    var shallowEqual = require('fbjs/lib/shallowEqual');  
      
    // 判断组件重绘时是采用更新组件实例的方式(返回真值);还是采用销毁实例后、重新创建实例的方式(返回否值)  
    // 组件元素的构造函数或key值不同,销毁实例后再行创建  
    var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');  
      
    // warning(condition,format) condition为否值,替换format中的"%s",并console.error警告   
    var warning = require('fbjs/lib/warning');  
      
    // 区分纯函数无状态组件、PureComponent纯组件、Component组件的标识符  
    var CompositeTypes = {  
      ImpureClass: 0,// 组件,继承自React.Component  
      PureClass: 1,// 纯组件,继承自React.PureComponent,不能设置shouldComponentUpdate方法,重绘时判断props、state是否变更  
      StatelessFunctional: 2// 纯函数无状态组件,function(props,context,updateQueue){}形式  
    };  
      
    // 将无状态组件function(props,context,updateQueue){}包装为带有render原型方法的构造函数形式  
    function StatelessComponent(Component) {}  
    StatelessComponent.prototype.render = function () {  
      var Component = ReactInstanceMap.get(this)._currentElement.type;  
      var element = Component(this.props, this.context, this.updater);  
      warnIfInvalidElement(Component, element);  
      return element;  
    };  
      
    // 校验无状态组件返回值必须是ReactElement,以及不能设置childContextTypes静态属性  
    function warnIfInvalidElement(Component, element) {  
      if (process.env.NODE_ENV !== 'production') {  
        process.env.NODE_ENV !== 'production' ?   
          warning(element === null || element === false || React.isValidElement(element),   
            '%s(...): A valid React element (or null) must be returned. You may have '   
            + 'returned undefined, an array or some other invalid object.',   
            Component.displayName || Component.name || 'Component')   
          : void 0;  
        process.env.NODE_ENV !== 'production' ?   
          warning(!Component.childContextTypes,   
            '%s(...): childContextTypes cannot be defined on a functional component.',   
            Component.displayName || Component.name || 'Component')   
          : void 0;  
      }  
    }  
      
    // 校验是否纯组件或组件;返回否值,当作非状态组件、或ReactClass的工厂函数处理  
    function shouldConstruct(Component) {  
      return !!(Component.prototype && Component.prototype.isReactComponent);  
    }  
      
    function isPureComponent(Component) {  
      return !!(Component.prototype && Component.prototype.isPureReactComponent);  
    }  
      
    // 开发环境下带调试方式执行fn  
    function measureLifeCyclePerf(fn, debugID, timerType) {  
      if (debugID === 0) {  
        // Top-level wrappers (see ReactMount) and empty components (see  
        // ReactDOMEmptyComponent) are invisible to hooks and devtools.  
        // Both are implementation details that should go away in the future.  
        return fn();  
      }  
      
      ReactInstrumentation.debugTool.onBeginLifeCycleTimer(debugID, timerType);  
      try {  
        return fn();  
      } finally {  
        ReactInstrumentation.debugTool.onEndLifeCycleTimer(debugID, timerType);  
      }  
    }  
      
    var nextMountID = 1;  
      
    // 自定义组件实例化、挂载、移除、更新实现  
    var ReactCompositeComponent = {  
      // 实例化  
      construct: function (element) {  
        this._currentElement = element;// ReactComponentElement,配置了组件的构造函数、props属性等  
        this._rootNodeID = 0;  
        this._compositeType = null;// 区分纯函数无状态组件、继承自PureComponent的纯组件、以及继承自Component的组件  
        this._instance = null;// ReactComponent实例  
        this._hostParent = null;// 文档元素,作为组件元素的父节点  
        this._hostContainerInfo = null;  
      
        // See ReactUpdateQueue  
        this._updateBatchNumber = null;  
        this._pendingElement = null;// ReactDom.render方法渲染时包裹元素由react组件渲染,_pendingElement存储待渲染元素  
        this._pendingStateQueue = null;// 组件调用setState、replaceState方法,通过ReactUpdateQueue将更迭后的state推入_pendingStateQueue  
        this._pendingReplaceState = false;// 判断组件是否通过调用replaceState方法向_pendingStateQueue推入state数据  
        this._pendingForceUpdate = false;// 组件调用forceUpdate赋值为真  
      
        this._renderedNodeType = null;// 节点类型,区分ReactComponentElement、ReactDomElement元素  
        this._renderedComponent = null;// render方法内子组件实例  
        this._context = null;// 赋值给组件的context属性  
        this._mountOrder = 0;// 挂载的第几个组件  
        this._topLevelWrapper = null;  
      
        // See ReactUpdates and ReactUpdateQueue.  
        this._pendingCallbacks = null;  
      
        // ComponentWillUnmount shall only be called once  
        this._calledComponentWillUnmount = false;  
      
        if (process.env.NODE_ENV !== 'production') {  
          this._warnedAboutRefsInRender = false;  
        }  
      },  
      
      // 由ReactReconciler.mountComponent方法发起  
      
      // 关于参数:  
      // 参数transaction默认为ReactUpdates.ReactReconcileTransaction,即ReactReconcileTransaction模块  
      //    用于在组件元素挂载前后执行指定的钩子函数,选中文本回撤、阻止事件触发、生命周期钩子和调试等  
      //    特别是通过执行getReactMountReady().enqueue()方法,添加componentDidMount、componentDidUpdate生命周期钩子  
      //    其次是通过执行getUpdateQueue()方法,向组件实例注入updater参数,默认是ReactUpdateQueue模块  
      //    意义是为组件的setState、replaceState、forceUpdate方法完成功能提供必要的函数  
      // 参数context或者为空对象,或者由上层组件提供,后者混合this.context和this.getChildContext()形成  
      
      // 完成组件实例化,执行实例的render方法,通过ReactDomComponent绘制DomLazyTree,挂载componentDidMount函数  
      mountComponent: function (transaction, hostParent, hostContainerInfo, context) {  
        var _this = this;  
      
        this._context = context;  
        this._mountOrder = nextMountID++;  
        this._hostParent = hostParent;  
        this._hostContainerInfo = hostContainerInfo;  
      
        // 添加到ReactComponentElement元素的props属性  
        var publicProps = this._currentElement.props;  
      
        // 通过Component.contextTypes过滤由上层组件注入的context属性,并做校验  
        var publicContext = this._processContext(context);  
      
        // 纯函数无状态组件、或者继承自PureComponent的纯组件构造函数、或者继承自Component的组件构造函数  
        var Component = this._currentElement.type;  
      
        // 传入组件ReactComponent的第三个参数updater,默认是ReactUpdateQueue模块,用于实现setState等方法  
        var updateQueue = transaction.getUpdateQueue();  
      
        // 校验是否纯组件或组件;返回否值,当作非状态组件、或ReactClass的工厂函数处理  
        var doConstruct = shouldConstruct(Component);  
      
        // 创建纯组件或组件实例,或者获取无状态组件的返回值  
        var inst = this._constructComponent(doConstruct, publicProps, publicContext, updateQueue);  
      
        // 待挂载的ReactComponentElement元素  
        var renderedElement;  
      
        // Component为纯函数无状态组件书写方式  
        if (!doConstruct && (inst == null || inst.render == null)) {  
          // 无状态组件返回值即是待挂载的ReactElement  
          renderedElement = inst;  
      
          // 校验无状态组件返回值必须是ReactElement,以及不能设置childContextTypes静态属性  
          warnIfInvalidElement(Component, renderedElement);  
      
          // 校验无状态组件的返回值是否ReactElement  
          !(inst === null || inst === false || React.isValidElement(inst)) ?   
            process.env.NODE_ENV !== 'production' ?   
              invariant(false, '%s(...): A valid React element (or null) must be returned. '   
                + 'You may have returned undefined, an array or some other invalid object.',   
                Component.displayName || Component.name || 'Component')   
              : _prodInvariant('105', Component.displayName || Component.name || 'Component')   
              : void 0;  
            
          // 将无状态组件function(props,context,updateQueue){}包装为带有render原型方法的构造函数形式  
          inst = new StatelessComponent(Component);  
      
          // 添加无状态组件标识  
          this._compositeType = CompositeTypes.StatelessFunctional;  
      
        // Component为纯组件或组件形式  
        } else {  
          if (isPureComponent(Component)) {  
            // 添加纯组件标识  
            this._compositeType = CompositeTypes.PureClass;  
          } else {  
            // 添加组件标识  
            this._compositeType = CompositeTypes.ImpureClass;  
          }  
        }  
      
        // 实例没有render方法,或者props属性同publicProps不符,警告  
        if (process.env.NODE_ENV !== 'production') {  
          if (inst.render == null) {  
            process.env.NODE_ENV !== 'production' ?   
              warning(false, '%s(...): No `render` method found on the returned component '   
                + 'instance: you may have forgotten to define `render`.',   
                Component.displayName || Component.name || 'Component')   
              : void 0;  
          }  
      
          var propsMutated = inst.props !== publicProps;  
          var componentName = Component.displayName || Component.name || 'Component';  
      
          process.env.NODE_ENV !== 'production' ?   
            warning(inst.props === undefined || !propsMutated,   
              '%s(...): When calling super() in `%s`, make sure to pass '   
              + 'up the same props that your component\'s constructor was passed.',   
              componentName, componentName)   
            : void 0;  
        }  
      
        // 原本作为构造函数的参数传入,为方便起见,再次赋值,同时保证实例数据的准确性  
        inst.props = publicProps;  
        inst.context = publicContext;  
        inst.refs = emptyObject;  
        inst.updater = updateQueue;  
      
        this._instance = inst;  
      
        // ReactInstanceMap中添加组件实例  
        ReactInstanceMap.set(inst, this);  
      
        if (process.env.NODE_ENV !== 'production') {  
          // 组件不是由ReactClass方式创建,且添加了getInitialState或getDefaultProps方法,警告  
          process.env.NODE_ENV !== 'production' ?   
            warning(!inst.getInitialState || inst.getInitialState.isReactClassApproved || inst.state,   
              'getInitialState was defined on %s, a plain JavaScript class. '   
              + 'This is only supported for classes created using React.createClass. '   
              + 'Did you mean to define a state property instead?',   
              this.getName() || 'a component')   
            : void 0;  
          process.env.NODE_ENV !== 'production' ?   
            warning(!inst.getDefaultProps || inst.getDefaultProps.isReactClassApproved,   
              'getDefaultProps was defined on %s, a plain JavaScript class. '   
              + 'This is only supported for classes created using React.createClass. '   
              + 'Use a static property to define defaultProps instead.',   
              this.getName() || 'a component')   
            : void 0;  
      
          // 静态属性propTypes、contextTypes书写为原型属性提示,只构造函数拥有,实例没有  
          process.env.NODE_ENV !== 'production' ?   
            warning(!inst.propTypes,   
              'propTypes was defined as an instance property on %s. Use a static '   
              + 'property to define propTypes instead.', this.getName() || 'a component')   
            : void 0;  
          process.env.NODE_ENV !== 'production' ?   
            warning(!inst.contextTypes,   
              'contextTypes was defined as an instance property on %s. Use a '   
              + 'static property to define contextTypes instead.', this.getName() || 'a component')   
            : void 0;  
      
          // 接口变动更改  
          process.env.NODE_ENV !== 'production' ?   
            warning(typeof inst.componentShouldUpdate !== 'function', '%s has a method called '   
              + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? '   
              + 'The name is phrased as a question because the function is '   
              + 'expected to return a value.', this.getName() || 'A component')   
            : void 0;  
          process.env.NODE_ENV !== 'production' ?   
            warning(typeof inst.componentDidUnmount !== 'function', '%s has a method called '   
              + 'componentDidUnmount(). But there is no such lifecycle method. '   
              + 'Did you mean componentWillUnmount()?', this.getName() || 'A component')   
            : void 0;  
          process.env.NODE_ENV !== 'production' ?   
            warning(typeof inst.componentWillRecieveProps !== 'function', '%s has a method called '   
              + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',   
              this.getName() || 'A component')   
            : void 0;  
        }  
      
        // 获取初始state,并提示state只能设置为对象形式  
        var initialState = inst.state;  
        if (initialState === undefined) {  
          inst.state = initialState = null;  
        }  
        !(typeof initialState === 'object' && !Array.isArray(initialState)) ?   
          process.env.NODE_ENV !== 'production' ?   
            invariant(false, '%s.state: must be set to an object or null',   
              this.getName() || 'ReactCompositeComponent')   
            : _prodInvariant('106', this.getName() || 'ReactCompositeComponent')   
          : void 0;  
      
        this._pendingStateQueue = null;  
        this._pendingReplaceState = false;  
        this._pendingForceUpdate = false;  
      
        // 执行实例inst的render方法,嵌套调用mountComponent,将返回值ReactNode元素转化成DomLazyTree输出  
        var markup;  
        if (inst.unstable_handleError) {  
          markup = this.performInitialMountWithErrorHandling(renderedElement, hostParent, hostContainerInfo, transaction, context);  
        } else {  
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
        }  
      
        // 向后置钩子transaction.getReactMountReady()中添加实例的生命周期方法componentDidMount  
        if (inst.componentDidMount) {  
          if (process.env.NODE_ENV !== 'production') {  
            transaction.getReactMountReady().enqueue(function () {  
              measureLifeCyclePerf(function () {  
                return inst.componentDidMount();  
              }, _this._debugID, 'componentDidMount');  
            });  
          } else {  
            transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);  
          }  
        }  
      
        return markup;  
      },  
      
      // 创建纯组件或组件实例,或者获取无状态组件的返回值  
      _constructComponent: function (doConstruct, publicProps, publicContext, updateQueue) {  
        if (process.env.NODE_ENV !== 'production') {  
          ReactCurrentOwner.current = this;  
          try {  
            // 创建纯组件或组件实例,或者获取无状态组件的返回值  
            return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);  
          } finally {  
            ReactCurrentOwner.current = null;  
          }  
        } else {  
          return this._constructComponentWithoutOwner(doConstruct, publicProps, publicContext, updateQueue);  
        }  
      },  
      
      // 创建纯组件或组件实例,或者获取无状态组件的返回值  
      _constructComponentWithoutOwner: function (doConstruct, publicProps, publicContext, updateQueue) {  
        var Component = this._currentElement.type;  
      
        // Component为纯组件或组件,创建实例;Component可能为TopLevelWrapper  
        if (doConstruct) {  
          if (process.env.NODE_ENV !== 'production') {  
            return measureLifeCyclePerf(function () {  
              return new Component(publicProps, publicContext, updateQueue);  
            }, this._debugID, 'ctor');  
          } else {  
            return new Component(publicProps, publicContext, updateQueue);  
          }  
        }  
      
        // Component为工厂函数ReactClassFacory=function(props,context,updateQueue){  
        //     return new ReactClass(props,context,updateQueue)     
        // }  
        // 或者,无状态组件纯函数形式function(props,context,updateQueue){}  
        if (process.env.NODE_ENV !== 'production') {  
          return measureLifeCyclePerf(function () {  
            return Component(publicProps, publicContext, updateQueue);  
          }, this._debugID, 'render');  
        } else {  
          return Component(publicProps, publicContext, updateQueue);  
        }  
      },  
      
      performInitialMountWithErrorHandling: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {  
        var markup;  
        var checkpoint = transaction.checkpoint();  
        try {  
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
        } catch (e) {  
          // Roll back to checkpoint, handle error (which may add items to the transaction), and take a new checkpoint  
          transaction.rollback(checkpoint);  
          this._instance.unstable_handleError(e);  
          if (this._pendingStateQueue) {  
            // _processPendingState方法获取组件setState、replaceState方法执行后的最终state  
            this._instance.state = this._processPendingState(this._instance.props, this._instance.context);  
          }  
          checkpoint = transaction.checkpoint();  
      
          this._renderedComponent.unmountComponent(true);  
          transaction.rollback(checkpoint);  
      
          // Try again - we've informed the component about the error, so they can render an error message this time.  
          // If this throws again, the error will bubble up (and can be caught by a higher error boundary).  
          markup = this.performInitialMount(renderedElement, hostParent, hostContainerInfo, transaction, context);  
        }  
        return markup;  
      },  
      
      // 执行ReactComponent实例的render方法,获取其返回值ReactNode  
      // 嵌套调用mountComponent,完成ReactNode元素相应组件的实例化和render方法执行  
      // 最终通过ReactDomElement转化为DOMLazyTree对象输出,其node属性为需要插入文档dom对象  
      performInitialMount: function (renderedElement, hostParent, hostContainerInfo, transaction, context) {  
        var inst = this._instance;  
      
        var debugID = 0;  
        if (process.env.NODE_ENV !== 'production') {  
          debugID = this._debugID;  
        }  
      
        // 执行组件实例的componentWillMount方法  
        // componentWillMount方法内调用setState、replaceState,_pendingStateQueue有值,刷新state后再行绘制  
        if (inst.componentWillMount) {  
          if (process.env.NODE_ENV !== 'production') {  
            measureLifeCyclePerf(function () {  
              return inst.componentWillMount();  
            }, debugID, 'componentWillMount');  
          } else {  
            inst.componentWillMount();  
          }  
      
          if (this._pendingStateQueue) {  
            // _processPendingState方法获取组件setState、replaceState方法执行后的最终state  
            inst.state = this._processPendingState(inst.props, inst.context);  
          }  
        }  
      
        // 间接执行ReactClass或TopLevelWrapper实例的render方法,获取待挂载的元素ReactNode  
        // 组件若为函数式无状态组件function(props,context,updateQueue){},renderedElement由传参提供  
        if (renderedElement === undefined) {  
          // 调用组件实例inst的render方法,获取待挂载的元素ReactNode  
          renderedElement = this._renderValidatedComponent();  
        }  
      
        // 节点类型,ReactComponentElement元素返回1;ReactDomElement元素返回0;若为空,返回2  
        var nodeType = ReactNodeTypes.getType(renderedElement);  
        this._renderedNodeType = nodeType;  
      
        // 调用instantiateReactComponent模块以实例化render方法的返回值,即renderedElement元素  
        var child = this._instantiateReactComponent(renderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */  
        );  
      
        // render方法内子组件实例  
        this._renderedComponent = child;  
      
        // 嵌套调用mountComponent,完成renderedElement元素相应组件的实例化及render方法执行  
        // 最终通过ReactDomElement转化为DOMLazyTree对象输出,其node属性为需要插入文档dom对象  
        var markup = ReactReconciler.mountComponent(child, transaction, hostParent, hostContainerInfo, this._processChildContext(context), debugID);  
      
        if (process.env.NODE_ENV !== 'production') {  
          if (debugID !== 0) {  
            var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];  
            ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);  
          }  
        }  
      
        return markup;  
      },  
      
      // 由render方法内子组件实例,通过ReactDomComponent等,获取相应的dom节点  
      getHostNode: function () {  
        return ReactReconciler.getHostNode(this._renderedComponent);  
      },  
      
      // 移除组件,执行componentWillUnmount方法  
      unmountComponent: function (safely) {  
        if (!this._renderedComponent) {  
          return;  
        }  
      
        var inst = this._instance;  
      
        if (inst.componentWillUnmount && !inst._calledComponentWillUnmount) {  
          inst._calledComponentWillUnmount = true;  
      
          if (safely) {  
            var name = this.getName() + '.componentWillUnmount()';  
            ReactErrorUtils.invokeGuardedCallback(name, inst.componentWillUnmount.bind(inst));  
          } else {  
            if (process.env.NODE_ENV !== 'production') {  
              measureLifeCyclePerf(function () {  
                return inst.componentWillUnmount();  
              }, this._debugID, 'componentWillUnmount');  
            } else {  
              inst.componentWillUnmount();  
            }  
          }  
        }  
      
        if (this._renderedComponent) {  
          ReactReconciler.unmountComponent(this._renderedComponent, safely);  
          this._renderedNodeType = null;  
          this._renderedComponent = null;  
          this._instance = null;  
        }  
      
        this._pendingStateQueue = null;  
        this._pendingReplaceState = false;  
        this._pendingForceUpdate = false;  
        this._pendingCallbacks = null;  
        this._pendingElement = null;  
      
        this._context = null;  
        this._rootNodeID = 0;  
        this._topLevelWrapper = null;  
      
        ReactInstanceMap.remove(inst);  
      },  
      
      // 通过Component.contextTypes过滤由上层组件注入的context属性,仅保留Component.contextTypes约定的  
      _maskContext: function (context) {  
        var Component = this._currentElement.type;  
        var contextTypes = Component.contextTypes;  
        if (!contextTypes) {  
          return emptyObject;  
        }  
        var maskedContext = {};  
        for (var contextName in contextTypes) {  
          maskedContext[contextName] = context[contextName];  
        }  
        return maskedContext;  
      },  
      
      // 通过Component.contextTypes过滤由上层组件注入的context属性,并做校验  
      _processContext: function (context) {  
        var maskedContext = this._maskContext(context);  
        if (process.env.NODE_ENV !== 'production') {  
          var Component = this._currentElement.type;  
          if (Component.contextTypes) {  
            this._checkContextTypes(Component.contextTypes, maskedContext, 'context');  
          }  
        }  
        return maskedContext;  
      },  
      
      // 将当前组件的Context注入子组件;执行getChildContext方法并作校验,注入子组件的context中  
      _processChildContext: function (currentContext) {  
        var Component = this._currentElement.type;  
        var inst = this._instance;  
        var childContext;  
      
        if (inst.getChildContext) {  
          if (process.env.NODE_ENV !== 'production') {  
            ReactInstrumentation.debugTool.onBeginProcessingChildContext();  
            try {  
              childContext = inst.getChildContext();  
            } finally {  
              ReactInstrumentation.debugTool.onEndProcessingChildContext();  
            }  
          } else {  
            childContext = inst.getChildContext();  
          }  
        }  
      
        if (childContext) {  
          !(typeof Component.childContextTypes === 'object') ?   
            process.env.NODE_ENV !== 'production' ?   
              invariant(false, '%s.getChildContext(): '   
                + 'childContextTypes must be defined in order to use getChildContext().',   
                this.getName() || 'ReactCompositeComponent')   
              : _prodInvariant('107', this.getName() || 'ReactCompositeComponent')   
            : void 0;  
      
          if (process.env.NODE_ENV !== 'production') {  
            this._checkContextTypes(Component.childContextTypes, childContext, 'childContext');  
          }  
          for (var name in childContext) {  
            !(name in Component.childContextTypes) ?   
              process.env.NODE_ENV !== 'production' ?   
                invariant(false, '%s.getChildContext(): key "%s" is not defined in childContextTypes.',   
                  this.getName() || 'ReactCompositeComponent', name)   
                : _prodInvariant('108', this.getName() || 'ReactCompositeComponent', name)   
              : void 0;  
          }  
          return _assign({}, currentContext, childContext);  
        }  
        return currentContext;  
      },  
      
      // 校验context  
      _checkContextTypes: function (typeSpecs, values, location) {  
        if (process.env.NODE_ENV !== 'production') {  
          checkReactTypeSpec(typeSpecs, values, location, this.getName(), null, this._debugID);  
        }  
      },  
      
      // 接受新的组件待渲染元素nextElement,以替换旧的组件元素this._currentElement  
      // 通过performUpdateIfNecessary方法调用,nextElement由this._pendingElement提供  
      //    该方法触发执行的实际情形是ReactDom.render(ReactNode,pNode)挂载的组件元素,其父节点pNode由react方式绘制  
      // 通过_updateRenderedComponent方法调用,nextElement为待变更的子组件元素  
      receiveComponent: function (nextElement, transaction, nextContext) {  
        var prevElement = this._currentElement;  
        var prevContext = this._context;  
      
        this._pendingElement = null;  
      
        this.updateComponent(transaction, prevElement, nextElement, prevContext, nextContext);  
      },  
      
      // 由ReactDom.render(ReactNode,pNode)方法插入文档时,pNode由react方式绘制  
      //    调用ReactReconciler.receiveComponent间接执行updateComponent方法重绘组件  
      // 组件的setState、replaceState、forceUpdate方法触发重绘,直接调用updateComponent方法重绘组件  
      performUpdateIfNecessary: function (transaction) {  
        // ReactDom.render方法渲染时包裹元素由react组件渲染,将待渲染元素推入_pendingElement中  
        if (this._pendingElement != null) {  
          ReactReconciler.receiveComponent(this, this._pendingElement, transaction, this._context);  
      
        // 通过调用组件的setState、replaceState、forceUpdate方法重绘组件  
        } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {  
          this.updateComponent(transaction, this._currentElement, this._currentElement, this._context, this._context);  
          
        } else {  
          this._updateBatchNumber = null;  
        }  
      },  
      
      // 判断props变更情况,执行shouldComponentUpdate方法,重绘组件或者更改组件的属性  
      // 参数transaction,组件重绘时用于向子组件提供updater参数,setState等方法可用;以及实现componentWillMount挂载功能  
      // 参数prevParentElement变更前的组件元素ReactNode,nextParentElement变更后的组件元素,作为render方法渲染节点的父元素  
      // 参数prevUnmaskedContext更迭前的context,nextUnmaskedContext更迭后的context  
      updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext) {  
        var inst = this._instance;  
      
        // 组件实例尚未生成,报错  
        !(inst != null) ? process.env.NODE_ENV !== 'production' ?   
          invariant(false,   
            'Attempted to update component `%s` that has already been unmounted (or failed to mount).',   
            this.getName() || 'ReactCompositeComponent')   
          : _prodInvariant('136', this.getName() || 'ReactCompositeComponent')   
          : void 0;  
      
        var willReceive = false;  
        var nextContext;  
      
        // 更新context  
        if (this._context === nextUnmaskedContext) {  
          nextContext = inst.context;  
        } else {  
          nextContext = this._processContext(nextUnmaskedContext);  
          willReceive = true;  
        }  
      
        var prevProps = prevParentElement.props;  
        var nextProps = nextParentElement.props;  
      
        // 包含仅待渲染元素的props变更  
        if (prevParentElement !== nextParentElement) {  
          willReceive = true;  
        }  
      
        // 更新context、或变更带渲染组件元素或其props时willReceive赋值为真,由父组件发起,调用componentWillReceiveProps方法  
        if (willReceive && inst.componentWillReceiveProps) {  
          if (process.env.NODE_ENV !== 'production') {  
            measureLifeCyclePerf(function () {  
              return inst.componentWillReceiveProps(nextProps, nextContext);  
            }, this._debugID, 'componentWillReceiveProps');  
          } else {  
            inst.componentWillReceiveProps(nextProps, nextContext);  
          }  
        }  
      
        // _processPendingState方法获取组件setState、replaceState方法执行后的最终state  
        var nextState = this._processPendingState(nextProps, nextContext);  
        var shouldUpdate = true;  
      
        // 调用组件的shouldComponentUpdate判断是否需要重绘  
        // 纯组件不能设置shouldComponentUpdate方法,仅判断props、state是否变更  
        if (!this._pendingForceUpdate) {  
          if (inst.shouldComponentUpdate) {  
            if (process.env.NODE_ENV !== 'production') {  
              shouldUpdate = measureLifeCyclePerf(function () {  
                return inst.shouldComponentUpdate(nextProps, nextState, nextContext);  
              }, this._debugID, 'shouldComponentUpdate');  
            } else {  
              shouldUpdate = inst.shouldComponentUpdate(nextProps, nextState, nextContext);  
            }  
          } else {  
            if (this._compositeType === CompositeTypes.PureClass) {  
              shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState);  
            }  
          }  
        }  
      
        // shouldComponentUpdate方法返回undefined,警告  
        if (process.env.NODE_ENV !== 'production') {  
          process.env.NODE_ENV !== 'production' ?   
            warning(shouldUpdate !== undefined,   
              '%s.shouldComponentUpdate(): Returned undefined instead of a '   
              + 'boolean value. Make sure to return true or false.',   
              this.getName() || 'ReactCompositeComponent')   
            : void 0;  
        }  
      
        this._updateBatchNumber = null;  
      
        // 重绘组件  
        if (shouldUpdate) {  
          this._pendingForceUpdate = false;  
      
          // 执行componentWillUpdate方法,重绘组件实例render方法内待渲染的子组件,挂载componentDidUpdate方法  
          this._performComponentUpdate(nextParentElement, nextProps, nextState, nextContext, transaction, nextUnmaskedContext);  
          
        // 只变更组件的部分属性,不开启重绘功能  
        } else {  
          this._currentElement = nextParentElement;  
          this._context = nextUnmaskedContext;  
          inst.props = nextProps;  
          inst.state = nextState;  
          inst.context = nextContext;  
        }  
      },  
      
      // 获取组件setState、replaceState方法执行后的最终state  
      // setState、replaceState方法执行后更迭的state以函数或state数据形式推入_pendingStateQueue中  
      _processPendingState: function (props, context) {  
        var inst = this._instance;  
        var queue = this._pendingStateQueue;  
        var replace = this._pendingReplaceState;  
        this._pendingReplaceState = false;  
        this._pendingStateQueue = null;  
      
        if (!queue) {  
          return inst.state;  
        }  
      
        if (replace && queue.length === 1) {  
          return queue[0];  
        }  
      
        var nextState = _assign({}, replace ? queue[0] : inst.state);  
        for (var i = replace ? 1 : 0; i < queue.length; i++) {  
          var partial = queue[i];  
          _assign(nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) : partial);  
        }  
      
        return nextState;  
      },  
      
      // 执行componentWillUpdate方法,重绘组件实例render方法内待渲染的子组件,挂载componentDidUpdate方法  
      _performComponentUpdate: function (nextElement, nextProps, nextState, nextContext, transaction, unmaskedContext) {  
        var _this2 = this;  
      
        var inst = this._instance;  
      
        var hasComponentDidUpdate = Boolean(inst.componentDidUpdate);  
        var prevProps;  
        var prevState;  
        var prevContext;  
        if (hasComponentDidUpdate) {  
          prevProps = inst.props;  
          prevState = inst.state;  
          prevContext = inst.context;  
        }  
      
        // 执行componentWillUpdate方法  
        if (inst.componentWillUpdate) {  
          if (process.env.NODE_ENV !== 'production') {  
            measureLifeCyclePerf(function () {  
              return inst.componentWillUpdate(nextProps, nextState, nextContext);  
            }, this._debugID, 'componentWillUpdate');  
          } else {  
            inst.componentWillUpdate(nextProps, nextState, nextContext);  
          }  
        }  
      
        this._currentElement = nextElement;  
        this._context = unmaskedContext;  
        inst.props = nextProps;  
        inst.state = nextState;  
        inst.context = nextContext;  
      
        // 以更新子组件的方式或重新创建子组件的方式重绘render方法待渲染的子组件  
        this._updateRenderedComponent(transaction, unmaskedContext);  
      
        // 向后置钩子transaction.getReactMountReady()中添加实例的生命周期方法componentDidUpdate  
        if (hasComponentDidUpdate) {  
          if (process.env.NODE_ENV !== 'production') {  
            transaction.getReactMountReady().enqueue(function () {  
              measureLifeCyclePerf(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), _this2._debugID, 'componentDidUpdate');  
            });  
          } else {  
            transaction.getReactMountReady().enqueue(inst.componentDidUpdate.bind(inst, prevProps, prevState, prevContext), inst);  
          }  
        }  
      },  
      
      // 以更新子组件的方式或重新创建子组件的方式重绘render方法待渲染的子组件  
      _updateRenderedComponent: function (transaction, context) {  
        var prevComponentInstance = this._renderedComponent;// 组件render待渲染的子组件实例  
        var prevRenderedElement = prevComponentInstance._currentElement;// 子组件元素  
      
        // _renderValidatedComponent方法调用组件实例inst的render方法,获取待挂载的元素  
        var nextRenderedElement = this._renderValidatedComponent();  
      
        var debugID = 0;  
        if (process.env.NODE_ENV !== 'production') {  
          debugID = this._debugID;  
        }  
      
        // shouldUpdateReactComponent方法返回真值,更新组件实例;返回否值,销毁实例后、重新创建实例  
        // 组件元素的构造函数或key值不同,销毁实例后再行创建  
      
        // render方法子组件构造函数及key相同,通过ReactReconciler.receiveComponent方法更新子组件实例  
        if (shouldUpdateReactComponent(prevRenderedElement, nextRenderedElement)) {  
          ReactReconciler.receiveComponent(prevComponentInstance, nextRenderedElement, transaction, this._processChildContext(context));  
          
        // render方法子组件构造函数或key不同,重新创建子组件实例后,调用_replaceNodeWithMarkup方法替换挂载元素  
        } else {  
          var oldHostNode = ReactReconciler.getHostNode(prevComponentInstance);  
          ReactReconciler.unmountComponent(prevComponentInstance, false);  
      
          var nodeType = ReactNodeTypes.getType(nextRenderedElement);  
          this._renderedNodeType = nodeType;  
          var child = this._instantiateReactComponent(nextRenderedElement, nodeType !== ReactNodeTypes.EMPTY /* shouldHaveDebugID */  
          );  
          this._renderedComponent = child;  
      
          var nextMarkup = ReactReconciler.mountComponent(child, transaction, this._hostParent, this._hostContainerInfo, this._processChildContext(context), debugID);  
      
          if (process.env.NODE_ENV !== 'production') {  
            if (debugID !== 0) {  
              var childDebugIDs = child._debugID !== 0 ? [child._debugID] : [];  
              ReactInstrumentation.debugTool.onSetChildren(debugID, childDebugIDs);  
            }  
          }  
      
          // 替换文档中挂载的Dom元素DomLazyTree  
          this._replaceNodeWithMarkup(oldHostNode, nextMarkup, prevComponentInstance);  
        }  
      },  
      
      // 替换文档中挂载的Dom元素DomLazyTree  
      _replaceNodeWithMarkup: function (oldHostNode, nextMarkup, prevInstance) {  
        ReactComponentEnvironment.replaceNodeWithMarkup(oldHostNode, nextMarkup, prevInstance);  
      },  
      
      // 调用组件实例inst的render方法,获取待挂载的元素  
      _renderValidatedComponentWithoutOwnerOrContext: function () {  
        var inst = this._instance;  
        var renderedElement;  
      
        if (process.env.NODE_ENV !== 'production') {  
          renderedElement = measureLifeCyclePerf(function () {  
            return inst.render();  
          }, this._debugID, 'render');  
        } else {  
          renderedElement = inst.render();  
        }  
      
        if (process.env.NODE_ENV !== 'production') {  
          if (renderedElement === undefined && inst.render._isMockFunction) {  
            renderedElement = null;  
          }  
        }  
      
        return renderedElement;  
      },  
      
      // 调用组件实例inst的render方法,获取待挂载的元素  
      _renderValidatedComponent: function () {  
        var renderedElement;  
        if (process.env.NODE_ENV !== 'production' || this._compositeType !== CompositeTypes.StatelessFunctional) {  
          ReactCurrentOwner.current = this;  
          try {  
            renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();  
          } finally {  
            ReactCurrentOwner.current = null;  
          }  
        } else {  
          renderedElement = this._renderValidatedComponentWithoutOwnerOrContext();  
        }  
      
        // 校验renderedElement是否为ReactElement  
        !(renderedElement === null || renderedElement === false || React.isValidElement(renderedElement))   
          ? process.env.NODE_ENV !== 'production' ?   
            invariant(false, '%s.render(): A valid React element (or null) must be returned. '   
              + 'You may have returned undefined, an array or some other invalid object.',   
              this.getName() || 'ReactCompositeComponent')   
            : _prodInvariant('109', this.getName() || 'ReactCompositeComponent')   
          : void 0;  
      
        return renderedElement;  
      },  
      
      // 对外提供接口,用于向组件实例ReactComponentInstance添加this.refs属性  
      attachRef: function (ref, component) {// 参数component为子组件  
        var inst = this.getPublicInstance();  
      
        // 无状态组件没有this.refs属性  
        !(inst != null) ? process.env.NODE_ENV !== 'production' ?   
          invariant(false, 'Stateless function components cannot have refs.')   
          : _prodInvariant('110') : void 0;  
      
        var publicComponentInstance = component.getPublicInstance();// 子组件的实例  
      
        // 无状态子组件也不能作为上层组件的this.refs的值  
        if (process.env.NODE_ENV !== 'production') {  
          var componentName = component && component.getName ? component.getName() : 'a component';  
          process.env.NODE_ENV !== 'production' ?   
            warning(publicComponentInstance != null   
              || component._compositeType !== CompositeTypes.StatelessFunctional,   
              'Stateless function components cannot be given refs '   
              + '(See ref "%s" in %s created by %s). ' + 'Attempts to access this ref will fail.',   
              ref, componentName, this.getName())   
            : void 0;  
        }  
      
        // 通过引用对象的形式赋值inst.refs  
        var refs = inst.refs === emptyObject ? inst.refs = {} : inst.refs;  
        refs[ref] = publicComponentInstance;  
      },  
      
      // 销毁组件实例ReactComponentInstance的refs属性  
      detachRef: function (ref) {  
        var refs = this.getPublicInstance().refs;  
        delete refs[ref];  
      },  
      
      // 获取组件名  
      getName: function () {  
        var type = this._currentElement.type;  
        var constructor = this._instance && this._instance.constructor;  
        return type.displayName || constructor && constructor.displayName || type.name || constructor && constructor.name || null;  
      },  
      
      // 获取组件ReactComponent的实例  
      getPublicInstance: function () {  
        var inst = this._instance;  
        if (this._compositeType === CompositeTypes.StatelessFunctional) {  
          return null;  
        }  
        return inst;  
      },  
      
      // 调用instantiateReactComponent模块,用于创建子组件  
      _instantiateReactComponent: null  
      
    };  
      
    module.exports = ReactCompositeComponent;  

    相关文章

      网友评论

        本文标题:阅读react源码:(一).组件的实例化,元素挂载,重绘rend

        本文链接:https://www.haomeiwen.com/subject/ratloxtx.html