react中render的源码学习

2019-04-24  本文已影响0人  beat_3e68

ReactMount = {
// ReactDOM.render直接引用此方法
render: function (nextElement, container, callback) {
return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
},
// 实际执行render的方法
_renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');

// 将传入的element用TopLevelWrapper包装,
// 包装后的元素,标记有rootID,并且拥有render方法,
// 具体可看TopLevelWrapper的源码
var nextWrappedElement = React.createElement(TopLevelWrapper, {
  child: nextElement
});

// ReactDOM.render方法调用时,parentComponent为null
var nextContext;
if (parentComponent) {
  var parentInst = ReactInstanceMap.get(parentComponent);
  nextContext = parentInst._processChildContext(parentInst._context);
} else {
  nextContext = emptyObject;
}

// 第一次执行时,prevComponent为null,具体可看此方法源码
var prevComponent = getTopLevelWrapperInContainer(container);

if (prevComponent) {
  var prevWrappedElement = prevComponent._currentElement;
  var prevElement = prevWrappedElement.props.child;

  // 判断上一次的prevElement和nextElement是否是同一个组件,或者仅仅是数字、字符串,如果是,则直接update,
  // 否则,重新渲染整个Element
  if (shouldUpdateReactComponent(prevElement, nextElement)) {
    var publicInst = prevComponent._renderedComponent.getPublicInstance();
    var updatedCallback = callback && function () {
      callback.call(publicInst);
    };
    // 更新vdom
    ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);
    return publicInst;
  } else {
    ReactMount.unmountComponentAtNode(container);
  }
}

var reactRootElement = getReactRootElementInContainer(container);
var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);
var containerHasNonRootReactChild = hasNonRootReactChild(container);


var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;
// 本次为首次渲染,因此调用ReactMount._renderNewRootComponent
var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();
if (callback) {
  callback.call(component);
}
return component;

},
/**

ReactBrowserEventEmitter.ensureScrollValueMonitoring();
// 初始化组件实例,并增加组件挂载(mount)、更新(update)、卸载(unmount)等方法
var componentInstance = instantiateReactComponent(nextElement, false);

// The initial render is synchronous but any updates that happen during
// rendering, in componentWillMount or componentDidMount, will be batched
// according to the current batching strategy.

ReactUpdates.batchedUpdates(batchedMountComponentIntoNode, componentInstance, container, shouldReuseMarkup, context);

var wrapperID = componentInstance._instance.rootID;
instancesByReactRootID[wrapperID] = componentInstance;

return componentInstance;

},
}

上一篇下一篇

猜你喜欢

热点阅读