美文网首页Web前端之路
React基础渲染机制

React基础渲染机制

作者: 皮神雷卡丘 | 来源:发表于2019-09-29 15:04 被阅读0次

    ReactDOM.js

    var ReactDOM = {
      findDOMNode: findDOMNode,
      render: ReactMount.render,
      unmountComponentAtNode: ReactMount.unmountComponentAtNode,
      version: ReactVersion,
    
      /* eslint-disable camelcase */
      unstable_batchedUpdates: ReactUpdates.batchedUpdates,
      unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
      /* eslint-enable camelcase */
    };
    

    ReactDOM.render()

    ReactDOM.render()方法来自ReactMount文件的render方法:

    render: function (nextElement, container, callback) {
        return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
      },
    

    Render()将子树nextElement注入到指定的container中,并调用其回调方法_renderSubtreeIntoContainer,它将完成
    (1)React.createElement 生成待插入节点的虚拟DOM实例对象
    (2)对新旧虚拟DOM进行对比,找到需要更新的地方批量改动。初次渲染直接将虚拟DOM转换为真实DOM
    (3)将DOM插入到container中

    Diff 算法

    简单mark一下(详细了解需要去看专门的文档):
    1.不同的节点类型 直接删去旧的节点,新建一个新的节点。
    2.相同节点类型 如果没有key对比它们的属性,只改变需要改变的属性,如果配置了key将作为唯一的节点不是改变其属性,而是直接操作此节点。

    _renderSubtreeIntoContainer

    _renderSubtreeIntoContainer: function (parentComponent, nextElement, container, callback) {
      /*
      *将callback放入到React的更新队列中,判断nextElement有效性以及当前是发开环境还是生产环境。(代码省略)
      */
      …
      var nextWrappedElement = React.createElement(TopLevelWrapper, { child: nextElement });
      // 返回一个ReactElement实例对象,也就是虚拟DOM的实例对象,下面就要把它渲染出来
      var nextContext;
      /*(1)判断是否有parentComponent,如果有则将其写到parentComponent*/
      if (parentComponent) {
        var parentInst = ReactInstanceMap.get(parentComponent);
        nextContext = parentInst._processChildContext(parentInst._context);
      } else {
        nextContext = emptyObject;
      }
      var prevComponent = getTopLevelWrapperInContainer(container);
      /*
     *(2)判断是否有prevComponent,如果有则取其child,利用Diff算法判断是否需要更新,如果需要则调用_updateRootComponen 方法,并return结果。对于初次渲染不需要该过程。 
     */
      if (prevComponent) {
        var prevWrappedElement = prevComponent._currentElement;
        var prevElement = prevWrappedElement.props.child;
        // shouldUpdateReactComponent方法判断是否需要更新,对同一DOM进行比较,type相同,key(如果有)相同的组件做DOM diff 
        if (shouldUpdateReactComponent(prevElement, nextElement)) {
          var publicInst = prevComponent._renderedComponent.getPublicInstance();
          var updatedCallback = callback && function () {
            callback.call(publicInst);
          };
          ReactMount._updateRootComponent(prevComponent, nextWrappedElement, nextContext, container, updatedCallback);
          return publicInst;
        } else {
          ReactMount.unmountComponentAtNode(container);
        }
      }
      /*
      *(3)对于prevElement为null直接跳到此步
      var reactRootElement = getReactRootElementInContainer(container);
      var containerHasReactMarkup = reactRootElement && !!internalGetID(reactRootElement);
      var containerHasNonRootReactChild = hasNonRootReactChild(container);
      var shouldReuseMarkup = containerHasReactMarkup && !prevComponent && !containerHasNonRootReactChild;
      /*
      *3核心部分,调用_renderNewRootComponent,_renderedComponent,getPublicInstance三个方法,
      */
      var component = ReactMount._renderNewRootComponent(nextWrappedElement, container, shouldReuseMarkup, nextContext)._renderedComponent.getPublicInstance();
      if (callback) {
        callback.call(component);
      }
      return component;
    }
    

    相关文章

      网友评论

        本文标题:React基础渲染机制

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