Mount根组件---起始篇

712 阅读2分钟

我们来看看React是如何挂载组件的 一个React项目有一个方法 render是整个React组件挂载的开始,也就是下面的这个方法。

ReactDOM.render(component,mountAt)

    '
        我们一般使用下面的方法来将组件挂载在根元素上
    '
        ReactDOM.render(<App />, document.getElementById("app"));
    
    '
        ReactDOM.render()方法是核心,它接收两个参数:
        Component:要挂载的组件。
        MountAt: document.getElementById("app"),我们再html中定义了一个根元素,其id为app,来挂载全部的React组件。
    '

ReactDOM.render方法最终是调用的 ReactMount模块的render方法,如下所示:

ReactMount.render

    render: function (nextElement, container, callback) {
        return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
    },
    '
        ReactMount.render方法实际上又是调用了 _renderSubtreeIntoContainer方法。这个方法是核心方法,顾名思义,该方法就是 render subtree into container:将子树挂载到 container内。
    '

ReactDOM.render方法的核心是调用了下边的这个方法。

瞧一瞧 _renderSubtreeIntoContainer 方法

    该方法接收四个参数。
    parentComponent:父组件,初始的时候这个值是null
    nextElement:就是要插入的组件
    container:就是要插如的容器,一般是document.getElementById('app')
    callback: 插入成功后的回调。

我们将 该方法 也就是 挂载的核心方法 _renderSubtreeIntoContainer 分割为三个部分。

篇幅太长不利于阅读,所以我们分篇幅来细说。 我会以第一部分,第二部分来命名。本篇就命名为 起始篇

     _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
        
        
        '
            第一部分
        '
        var nextWrappedElement = new ReactElement(TopLevelWrapper, null, null, null, null, null, nextElement);
        
        var prevComponent = instancesByReactRootID[getReactRootID(container)];------(1)
        
        '第二部分'
        
        if (prevComponent) {
          var prevWrappedElement = prevComponent._currentElement;
         
          var prevElement = prevWrappedElement.props;
         
          if (shouldUpdateReactComponent(prevElement, nextElement)) {
            var publicInst = prevComponent._renderedComponent.getPublicInstance();
            var updatedCallback = callback && function () {
              callback.call(publicInst);
            };
            ReactMount._updateRootComponent(prevComponent, nextWrappedElement, 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;
        var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, parentComponent != null ? parentComponent._reactInternalInstance._processChildContext(parentComponent._reactInternalInstance._context) : emptyObject)._renderedComponent.getPublicInstance();
        if (callback) {
          callback.call(component);
        }
        return component;
      },

所以,ReactDOM.render 方法核心是调用了 ReactMount._renderSubtreeIntoContainer 方法来完成组件的挂载。