美文网首页
react中render的源码学习

react中render的源码学习

作者: beat_3e68 | 来源:发表于2019-04-24 16:07 被阅读0次

    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;
    

    },
    /**

    • Render a new component into the DOM. Hooked by hooks!
    • @param {ReactElement} nextElement element to render
    • @param {DOMElement} container container to render into
    • @param {boolean} shouldReuseMarkup if we should skip the markup insertion
    • @return {ReactComponent} nextComponent
      */
      _renderNewRootComponent: function (nextElement, container, shouldReuseMarkup, context) {
    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;
    

    },
    }

    相关文章

      网友评论

          本文标题:react中render的源码学习

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