1. 程式人生 > 其它 >初窺React-4(第一個方法)

初窺React-4(第一個方法)

  從第一個方法開始,來到ReactDOMLegacy.js的render方法,其中最主要呼叫了legacyRenderSubtreeIntoContainer 方法,進入到該方法內部.

functionlegacyRenderSubtreeIntoContainer(parentComponent,children,container,forceHydrate,callback){ { topLevelUpdateWarnings(container); warnOnInvalidCallback$1(callback===undefined?null:callback,'render'); }//TODO:Without`any`type,Flowsays"Propertycannotbeaccessedonany //memberofintersectiontype."Whyyyyyy.

varroot=container._reactRootContainer; varfiberRoot;
if(!root){ //Initialmount root=container._reactRootContainer=legacyCreateRootFromDOMContainer(container,forceHydrate); fiberRoot=root._internalRoot;// 1.整個專案的根節點
if(typeofcallback==='function'){ varoriginalCallback=callback;
callback=function(){ varinstance=getPublicRootInstance(fiberRoot); //2.返回fiberNode的DOM節點 originalCallback.call(instance); }; }//Initialmountshouldnotbebatched.

unbatchedUpdates(function(){ updateContainer(children,fiberRoot,parentComponent,callback); }); }else{ fiberRoot=root._internalRoot;
if(typeofcallback==='function'){ var_originalCallback=callback;
callback=function(){ varinstance=getPublicRootInstance(fiberRoot);
_originalCallback.call(instance); }; }//Update

updateContainer(children,fiberRoot,parentComponent,callback); //3.開始REACT的主要工作,裡面包括優先順序入隊,虛擬dom, 雙快取切換,然後commit階段,後面會具體延申,這裡大概瞭解 }
returngetPublicRootInstance(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;
  }