码迷,mamicode.com
首页 > 其他好文 > 详细

初窥React-4(第一个方法)

时间:2021-06-20 17:52:31      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:loading   ace   style   server   too   rgba   nodetype   eve   global   

  从第一个方法开始,来到ReactDOMLegacy.js的render方法,其中最主要调用了 legacyRenderSubtreeIntoContainer 方法,进入到该方法内部.

function legacyRenderSubtreeIntoContainer(parentComponent, children, container, forceHydrate, callback) {
    {
      topLevelUpdateWarnings(container);
      warnOnInvalidCallback$1(callback === undefined ? null : callback, ‘render‘);
    } // TODO: Without `any` type, Flow says "Property cannot be accessed on any
    // member of intersection type." Whyyyyyy.


    var root = container._reactRootContainer;
    var fiberRoot; 

    if (!root) {
      // Initial mount
      root = container._reactRootContainer = legacyCreateRootFromDOMContainer(container, forceHydrate);
      fiberRoot = root._internalRoot; // 1.整个项目的根节点

      if (typeof callback === ‘function‘) {
        var originalCallback = callback;

        callback = function () {
          var instance = getPublicRootInstance(fiberRoot); //2.返回fiberNode的DOM节点
          originalCallback.call(instance);
        };
      } // Initial mount should not be batched.


      unbatchedUpdates(function () {
        updateContainer(children, fiberRoot, parentComponent, callback);
      });
    } else {
      fiberRoot = root._internalRoot;

      if (typeof callback === ‘function‘) {
        var _originalCallback = callback;

        callback = function () {
          var instance = getPublicRootInstance(fiberRoot);

          _originalCallback.call(instance);
        };
      } // Update


      updateContainer(children, fiberRoot, parentComponent, callback); //3.开始REACT的主要工作,里面包括优先级入队,虚拟dom, 双缓存切换,然后commit阶段,后面会具体延申,这里大概了解
    }

    return getPublicRootInstance(fiberRoot);
  }

1.fiberRoot的结构(一个FiberRootNode节点):

技术图片

 

 

 这里是获取FiberRootNode代码,可见这里create了LegacyRoot,实际调用ReactFiberReconciler包中的createContainer,抽到底就是new了个FiberRootNode对象出来

function legacyCreateRootFromDOMContainer(container, forceHydrate) {
    var shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container); // First clear any existing content.

    if (!shouldHydrate) {
      var warned = false;
      var rootSibling;

      while (rootSibling = container.lastChild) {
        {
          if (!warned && rootSibling.nodeType === ELEMENT_NODE && rootSibling.hasAttribute(ROOT_ATTRIBUTE_NAME)) {
            warned = true;

            error(‘render(): Target node has markup rendered by React, but there ‘ + ‘are unrelated nodes as well. This is most commonly caused by ‘ + ‘white-space inserted around server-rendered markup.‘);
          }
        }

        container.removeChild(rootSibling);
      }
    }

    {
      if (shouldHydrate && !forceHydrate && !warnedAboutHydrateAPI) {
        warnedAboutHydrateAPI = true;

        warn(‘render(): Calling ReactDOM.render() to hydrate server-rendered markup ‘ + ‘will stop working in React v18. Replace the ReactDOM.render() call ‘ + ‘with ReactDOM.hydrate() if you want React to attach to the server HTML.‘);
      }
    }

    return createLegacyRoot(container, shouldHydrate ? {
      hydrate: true
    } : undefined);
  }

抽到底(具体属性用到的时候再看):

function FiberRootNode(containerInfo, tag, hydrate) {
    this.tag = tag;
    this.containerInfo = containerInfo;
    this.pendingChildren = null;
    this.current = null;
    this.pingCache = null;
    this.finishedWork = null;
    this.timeoutHandle = noTimeout;
    this.context = null;
    this.pendingContext = null;
    this.hydrate = hydrate;
    this.callbackNode = null;
    this.callbackPriority = NoLanePriority;
    this.eventTimes = createLaneMap(NoLanes);
    this.expirationTimes = createLaneMap(NoTimestamp);
    this.pendingLanes = NoLanes;
    this.suspendedLanes = NoLanes;
    this.pingedLanes = NoLanes;
    this.expiredLanes = NoLanes;
    this.mutableReadLanes = NoLanes;
    this.finishedLanes = NoLanes;
    this.entangledLanes = NoLanes;
    this.entanglements = createLaneMap(NoLanes);

    {
      this.mutableSourceEagerHydrationData = null;
    }

    {
      this.interactionThreadID = unstable_getThreadID();
      this.memoizedInteractions = new Set();
      this.pendingInteractionMap = new Map();
    }

    {
      switch (tag) {
        case BlockingRoot:
          this._debugRootType = ‘createBlockingRoot()‘;
          break;

        case ConcurrentRoot:
          this._debugRootType = ‘createRoot()‘;
          break;

        case LegacyRoot:
          this._debugRootType = ‘createLegacyRoot()‘;
          break;
      }
    }
  }

 2.这里直接返回当前current上面的child.stateNode(跟当前Fiber相关本地状态,比如浏览器环境就是DOM节点)

function getPublicRootInstance(container) {
    var containerFiber = container.current;

    if (!containerFiber.child) {
      return null;
    }

    switch (containerFiber.child.tag) {
      case HostComponent:  //HostComponent和default返回的同样的东西,因为,getPublicInstance直接返回了传入的参数
      return getPublicInstance(containerFiber.child.stateNode); 

    default:

      return containerFiber.child.stateNode;
} }

 3.react的主要工作这里:

function updateContainer(element, container, parentComponent, callback) {
    {
      onScheduleRoot(container, element);
    }

    var current$1 = container.current;
    // React按照事件的紧急程度,把它们划分成三个等级:
    // 离散事件(DiscreteEvent):click、keydown、focusin等,这些事件的触发不是连续的,优先级为0。
    // 用户阻塞事件(UserBlockingEvent):drag、scroll、mouseover等,特点是连续触发,阻塞渲染,优先级为1。
    // 连续事件(ContinuousEvent):canplay、error、audio标签的timeupdate和canplay,优先级最高,为2。
    var eventTime = requestEventTime();

    {
      // $FlowExpectedError - jest isn‘t a global, and isn‘t recognized outside of tests
      if (‘undefined‘ !== typeof jest) {
        warnIfUnmockedScheduler(current$1);
        warnIfNotScopedWithMatchingAct(current$1);
      }
    }

    var lane = requestUpdateLane(current$1);  //计算lane,优先级,赛车道路

    {
      markRenderScheduled(lane);
    }

    var context = getContextForSubtree(parentComponent);

    if (container.context === null) {
      container.context = context;
    } else {
      container.pendingContext = context;
    }

    {
      if (isRendering && current !== null && !didWarnAboutNestedUpdates) {
        didWarnAboutNestedUpdates = true;

        error(‘Render methods should be a pure function of props and state; ‘ + ‘triggering nested component updates from render is not allowed. ‘ + ‘If necessary, trigger nested updates in componentDidUpdate.\n\n‘ + ‘Check the render method of %s.‘, getComponentName(current.type) || ‘Unknown‘);
      }
    }
   //创建更新
    var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property 
    // being called "element".

    update.payload = {
      element: element
    };
    callback = callback === undefined ? null : callback;

    if (callback !== null) {
      {
        if (typeof callback !== ‘function‘) {
          error(‘render(...): Expected the last optional `callback` argument to be a ‘ + ‘function. Instead received: %s.‘, callback);
        }
      }

      update.callback = callback;
    }
//  更新入队列
    enqueueUpdate(current$1, update);
    // update对象创建完成后意味着需要对页面进行更新,会调用scheduleUpdateOnFiber进入调度
    scheduleUpdateOnFiber(current$1, lane, eventTime);
    return lane;
  }

 

初窥React-4(第一个方法)

标签:loading   ace   style   server   too   rgba   nodetype   eve   global   

原文地址:https://www.cnblogs.com/allenliu0927/p/14905292.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!