ReactChildReconciler

ReactChildReconciler模块用于挂载、卸载、或更新ReactDomComponent子组件。

 

'use strict';

var ReactReconciler = require('./ReactReconciler');

// 用于获取ReactCompositeComponent组件实例或ReactDomComponent组件实例
var instantiateReactComponent = require('./instantiateReactComponent');

// react组件的key值转译
var KeyEscapeUtils = require('./KeyEscapeUtils');

// 由组件的构造函数及key键是否相同,判断是否可以更新组件
var shouldUpdateReactComponent = require('./shouldUpdateReactComponent');

// 用于遍历props.children,触发执行instantiateChild函数,以对象形式获取相关ReactDomComponent组件实例
var traverseAllChildren = require('./traverseAllChildren');

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

var ReactComponentTreeHook;

if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV === 'test') {
  ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');
}

// 以集合childInstances获取react组件实例
function instantiateChild(childInstances, child, name, selfDebugID) {
  var keyUnique = childInstances[name] === undefined;
  if (process.env.NODE_ENV !== 'production') {
    if (!ReactComponentTreeHook) {
      ReactComponentTreeHook = require('react/lib/ReactComponentTreeHook');
    }
    if (!keyUnique) {
      // ReactComponentTreeHook.getStackAddendumByID当key值相同,获取祖先节点的信息,警告用
      process.env.NODE_ENV !== 'production' ? 
        warning(false, 'flattenChildren(...): Encountered two children with the same key, ' 
          + '`%s`. Child keys must be unique; when two children share a key, only ' 
          + 'the first child will be used.%s', 
          KeyEscapeUtils.unescape(name), ReactComponentTreeHook.getStackAddendumByID(selfDebugID)) 
        : void 0;
    }
  }
  if (child != null && keyUnique) {
    // 获取child对应的react组件实例,表现为ReactCompositeComponent实例或ReactDomComponent实例等
    childInstances[name] = instantiateReactComponent(child, true);
  }
}

// 用于装载、更新、或卸载ReactDomComponent子组件
// 被ReactMultiChild模块调用,用于管理ReactDomComponent的子组件节点
var ReactChildReconciler = {
  // 获取props.children相关react组件实例集合
  instantiateChildren: function (nestedChildNodes, transaction, context, selfDebugID // 0 in production and for roots
  ) {
    if (nestedChildNodes == null) {
      return null;
    }
    var childInstances = {};

    if (process.env.NODE_ENV !== 'production') {
      traverseAllChildren(nestedChildNodes, function (childInsts, child, name) {
        return instantiateChild(childInsts, child, name, selfDebugID);
      }, childInstances);
    } else {
      traverseAllChildren(nestedChildNodes, instantiateChild, childInstances);
    }
    return childInstances;
  },

  // 通过shouldUpdateReactComponent函数判断是否可以更新ReactDomComponent子组件;若不能,卸载组件,并装载新的子组件
  // 参数prevChildren组件中先前挂载的子节点,以key键作为标识,用于更新或移除
  // 参数nextChildren组件中即将挂载的子节点,以key键作为标识,同prevChildren比较后添加或更新
  // 参数mountImages更新为组件最终渲染的子节点图谱
  // 参数removedNodes更新为组件待移除的子节点
  // 参数transcation生命周期管理
  // 参数hostParent父节点信息
  updateChildren: function (prevChildren, nextChildren, mountImages, removedNodes, transaction, hostParent, hostContainerInfo, context, selfDebugID // 0 in production and for roots
  ) {
    if (!nextChildren && !prevChildren) {
      return;
    }
    var name;
    var prevChild;
    for (name in nextChildren) {
      if (!nextChildren.hasOwnProperty(name)) {
        continue;
      }
      prevChild = prevChildren && prevChildren[name];
      var prevElement = prevChild && prevChild._currentElement;
      var nextElement = nextChildren[name];
      if (prevChild != null && shouldUpdateReactComponent(prevElement, nextElement)) {
        ReactReconciler.receiveComponent(prevChild, nextElement, transaction, context);
        nextChildren[name] = prevChild;
      } else {
        if (prevChild) {
          removedNodes[name] = ReactReconciler.getHostNode(prevChild);
          ReactReconciler.unmountComponent(prevChild, false);
        }

        var nextChildInstance = instantiateReactComponent(nextElement, true);
        nextChildren[name] = nextChildInstance;

        var nextChildMountImage = ReactReconciler.mountComponent(nextChildInstance, transaction, hostParent, hostContainerInfo, context, selfDebugID);
        mountImages.push(nextChildMountImage);
      }
    }

    for (name in prevChildren) {
      if (prevChildren.hasOwnProperty(name) && !(nextChildren && nextChildren.hasOwnProperty(name))) {
        prevChild = prevChildren[name];
        removedNodes[name] = ReactReconciler.getHostNode(prevChild);
        ReactReconciler.unmountComponent(prevChild, false);
      }
    }
  },

  // 遍历props.children相关react组件实例,执行unmountComponent方法卸载组件
  unmountChildren: function (renderedChildren, safely) {
    for (var name in renderedChildren) {
      if (renderedChildren.hasOwnProperty(name)) {
        var renderedChild = renderedChildren[name];
        ReactReconciler.unmountComponent(renderedChild, safely);
      }
    }
  }

};

module.exports = ReactChildReconciler;

你可能感兴趣的:(javascript)