天天看點

react回調函數_react源碼個人筆記-版本17.0.0(筆記02修改)

react回調函數_react源碼個人筆記-版本17.0.0(筆記02修改)

React 初始化的函數函數為ReactDom.render(), 進行更新有三種方式 ReactDom.render(), setState, forceUpdate 等。

// render 定義(1)

// ReactDom 執行render 的方法
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMLegacy.js
// 目的: 調用legacyRenderSubtreeIntoContainer 函數
export function render(
 element: React$Element<any>,  // ReactElement 元素
 container: Container,  // 容器
 callback: ?Function,  // 回調函數
) {
 // 執行 legacyRenderSubtreeIntoContainer 方法
 return legacyRenderSubtreeIntoContainer(
    null,
    element,
    container,
    false,
    callback,
  );
}
           

備注: React 入口函數, 傳入的參數為element, 和container 等資訊, 回調函數一般不傳入, 傳入後會執行。

// legacyRenderSubtreeIntoContainer 函數定義(2)

// 定義   legacyRenderSubtreeIntoContainer 方法
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMLegacy.js
// 主體邏輯: 根據container.root 有無,判斷是否為初始後或更新,無: 執行生成fiberRoot, 再執行非批量
// 更新 ,有: 執行普通的更新
function legacyRenderSubtreeIntoContainer(
 parentComponent: ?React$Component<any, any>, // 初始為null 
 children: ReactNodeList,
 container: Container,
 forceHydrate: boolean,  // false 
 callback: ?Function,
) {
 
 // TODO: Without `any` type, Flow says "Property cannot be accessed on any
 // member of intersection type." Whyyyyyy.
 // 初始化, 無屬性, 
 let root: RootType = (container._reactRootContainer: any);
 let fiberRoot;
 // 初始化
 if (!root) {
 // Initial mount
 // 擷取_reactRootContainer 屬性
    root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
     container,
    forceHydrate,  // false
    );
    // 定義fiberRoot
     fiberRoot = root._internalRoot;
    if (typeof callback === 'function') {  // 回調函數
        const originalCallback = callback;  
       callback = function() {
       // 執行個體
       const instance = getPublicRootInstance(fiberRoot);
        originalCallback.call(instance);  // 最原始回調函數
      };
    }
     // Initial mount should not be batched.
      // 非批量更新的方式
     unbatchedUpdates(() => {  // 設定執行環境
         // 更新的節點, fiberRoot,   parentComponent 父節點   callback : 回調
        updateContainer(children, fiberRoot, parentComponent, callback);
    });
  } else {
     // 當具有root 時候, 更新的時候
       fiberRoot = root._internalRoot; //  fiberRoot
      if (typeof callback === 'function') {  // 具有回調函數
       const originalCallback = callback;
      callback = function() {  // 包裹回調函數
      // 執行個體
       const instance = getPublicRootInstance(fiberRoot);
       originalCallback.call(instance);  // 回調函數調用
      };
    }
       // Update  // 進行更新, 非批量更新
    updateContainer(children, fiberRoot, parentComponent, callback);  // null 回調
  }
   return getPublicRootInstance(fiberRoot);
}
           

備注: 通過container._reactRootContainer 建構基本的資訊,基本的結構資訊包含fiberRoot 和rootFiber, 應用更新的初始化和更新都是從fiberRoot開始。對回調函數進行包裹處理, 最後在unbatchedUpdates 執行回調函數, 初始化時,想最快速度展示頁面,進而是非批量同步更新。 root 存在時, 也可以進行更新,連續調用React.ReactDom, 會走存在的路線。

// 定義legacyCreateRootFromDOMContainer 方法(3)

// 定義legacyCreateRootFromDOMContainer 方法,
// 擷取root  // container._reactRootContainer
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMLegacy.js
/// 主題邏輯: 是否需要hydrate條件生成, 調用createLegacyRoot
function legacyCreateRootFromDOMContainer(
 container: Container,  // container
 forceHydrate: boolean,  // false 
): RootType {
  // 是否需要hydrate 的判斷, 可以忽略部分, 現在隻考察shouldHydrate 為false 的情況
 const shouldHydrate =
 forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
 // First clear any existing content.
 if (!shouldHydrate) {
   let warned = false;
    let rootSibling;
     // 清空原來container 中所有子元素
    while ((rootSibling = container.lastChild)) {
      container.removeChild(rootSibling);
    }
  }
 return createLegacyRoot(
     container,
     shouldHydrate
      ? {
     hydrate: true,
        }
      : undefined,
  );
}
           

// 定義shouldHydrateDueToLegacyHeuristic 方法(4)

// 函數shouldHydrateDueToLegacyHeuristic 定義 
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMLegacy.js
// 主體邏輯:  擷取rootElement 元素, 并 進行判斷
function shouldHydrateDueToLegacyHeuristic(container) {
 const rootElement = getReactRootElementInContainer(container);
 return !!(
 rootElement &&
 rootElement.nodeType === ELEMENT_NODE &&
 rootElement.hasAttribute(ROOT_ATTRIBUTE_NAME)
  );
}
           

// 定義getReactRootElementInContainer 方法(5)

// getReactRootElementInContainer 定義
代碼位置: src/react/packages/react-dom/src/client/ReactDOMLegacy.js
主題邏輯 : 先判斷存在,在判斷是否為document, 最後傳回第一個元素
function getReactRootElementInContainer(container: any) {
 if (!container) {
 return null;
  }
 // 是否為document 
 if (container.nodeType === DOCUMENT_NODE) {
 return container.documentElement;
  } else {
 // 第一個子節點
 return container.firstChild;
  }
}
           

// 定義 createLegacyRoot 方法(6)

// 調用 createLegacyRoot 方法
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMRoot.js
// 主題邏輯: // 傳入LegacyRoot 參數, 調用構造函數, 傳回值為container._reactRootContainer 對應的值
export function createLegacyRoot(
 container: Container,
 options?: RootOptions,
): RootType {       
 // LegacyRoot 遺留類型的root  options : null
 //  new ReactDOMBlockingRoot() 執行個體 對應root  即 container.reactRootContainer                
 return new ReactDOMBlockingRoot(container, LegacyRoot, options);  // LegacyRoot
}

//備注:   src/react/packages/react-reconciler/src/ReactRootTags.js
export type RootTag = 0 | 1 | 2;
export const LegacyRoot = 0;  // 即遺留的root
export const BlockingRoot = 1;  // 阻塞的root類型
export const ConcurrentRoot = 2;    // concurrentRoot
           

// 構造函數ReactDOMBlockingRoot 定義(7)

// ReactDOMBlockingRoot 構造函數的定義
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMRoot.js
// 主題邏輯; 在原執行個體上,增加屬性, _internalRoot 對應fiberRoot
function ReactDOMBlockingRoot(
 container: Container,
 tag: RootTag,  // rootTag的類型
 options: void | RootOptions,
) {
 
 // root / contain._reactRootContainer 的結果就是 ReactDOMBlockingRoot 執行個體
 // this._internalRoot 對應fiberRoot 屬性
 this._internalRoot = createRootImpl(container, tag, options);  // 
 // container  容器,  tag 類型    options  參數
}
           

// 函數createRootImpl 定義(8)

// 定義 createRootImpl 函數
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMRoot.js
// 主題邏輯: 1 fiberRoot的構造, 2 fiberRoot 和container關系, 3, 基本事件的挂載
// tag : 0 , options: undefined  // root 對應fiberRoot
function createRootImpl(
 container: Container,  // 容器類型
 tag: RootTag,  // rootTag 的類型
 options: void | RootOptions,
) {
 
 // Tag is either LegacyRoot or Concurrent Root
 // 服務端渲染的參數
 const hydrate = options != null && options.hydrate === true;
 // 服務端渲染的回調參數
 const hydrationCallbacks =(options != null && options.hydrationOptions) || null;
 const mutableSources =(options != null &&options.hydrationOptions != null && options.hydrationOptions.mutableSources) ||
 null;
 // 定義root 屬性
 
 // container  容器  tag: 0 hydrate : false, hydrationCallbacks : null
 // root 對應為fiberRoot 
 const root = createContainer(container, tag, hydrate, hydrationCallbacks);
 markContainerAsRoot(root.current, container);  // 
 // 設定container 與root.current 的關系
 const containerNodeType = container.nodeType;
 // enableEagerRootListeners  // true;  是否支援挂載到元素上
 // true
 if (enableEagerRootListeners) {
 // 根容器的節點, react 17 中的事件挂載
 const rootContainerElement =
 container.nodeType === COMMENT_NODE ? container.parentNode : container;
   listenToAllSupportedEvents(rootContainerElement);  // 挂載的節點
  } else {
 // 其他方式
 if (hydrate && tag !== LegacyRoot) {
 const doc =
 containerNodeType === DOCUMENT_NODE
          ? container
          : container.ownerDocument;
 // We need to cast this because Flow doesn't work
 // with the hoisted containerNodeType. If we inline
 // it, then Flow doesn't complain. We intentionally
 // hoist it to reduce code-size.
 eagerlyTrapReplayableEvents(container, ((doc: any): Document));
    } else if (
 containerNodeType !== DOCUMENT_FRAGMENT_NODE &&
 containerNodeType !== DOCUMENT_NODE
    ) {
 ensureListeningTo(container, 'onMouseEnter', null);
    }
  }
 // 服務端的參數
 if (mutableSources) {
 for (let i = 0; i < mutableSources.length; i++) {
 const mutableSource = mutableSources[i];
 registerMutableSourceForHydration(root, mutableSource);
    }
  }
 // root 的傳回
 return root;  // root 對應為fiberRoot 對象
}
           

// 函數createContainer 定義(9)

// 建立FiberRoot的方法
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiberReconciler.old.js
// 主體邏輯: 調用createFiberRoot 函數
//  containerInfo:  container   tag: 0, //  hydrate : false, hydrationCallbacks: null
export function createContainer(
 containerInfo: Container,
 tag: RootTag,  // rootTag 的類型
 hydrate: boolean,
 hydrationCallbacks: null | SuspenseHydrationCallbacks,
): OpaqueRoot {
 return createFiberRoot(containerInfo, tag, hydrate, hydrationCallbacks);
}
           

// 函數createFiberRoot 定義(10)

// 建立FiberRoot的節點
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiberRoot.old.js
// 主題邏輯: 1 建立fiberRoot 和rootFiber, 設立兩者關系, 初始化rootFiber 中updateQueue
export function createFiberRoot(
 containerInfo: any, 
 tag: RootTag,  // rootTag的類型
 hydrate: boolean,
 hydrationCallbacks: null | SuspenseHydrationCallbacks,
): FiberRoot {
   //  建立FiberRoot 節點  containerInfo 容器的資訊  tag:rooTag的資訊
   const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);
 // 
 if (enableSuspenseCallback) {
     root.hydrationCallbacks = hydrationCallbacks;
  }

 // Cyclic construction. This cheats the type system right now because
 // stateNode is any.
 // 擷取rootFiber
    const uninitializedFiber = createHostRootFiber(tag);  // 初始化rootFiber
    root.current = uninitializedFiber;  // FiberRoot 的current 執行rootFiber
    uninitializedFiber.stateNode = root;
   // rootFiber.stateNode  指向fiberRoot
    initializeUpdateQueue(uninitializedFiber); // rootFiber
    return root;
}
           

// FiberRootNode 構造函數定義(11)

// FiberRootNode 構造函數定義 // containerInfo 容器  tag: 0  hydrate: false 
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiberRoot.old.js
// 主題邏輯: 根據tag 建立fiberRoot 
function FiberRootNode(containerInfo, tag, hydrate) {
 
 // fiberRoot 對象,1: 整個應用的起點, 2, 包含應用挂載的目标節點
 // 3 記錄整個應用的更新過程的全部資訊
 // containerInfo  容器  tag  rootTag 類型    hydrate 
 this.tag = tag;  // tag: 0  // rootTag 類型
 
 // react的各種模式
 // NoMode = 0b00000;
 // StrictMode = 0b00001;
 // BlockingMode = 0b00010;
 // ConcurrentMode = 0b00100;
 // ProfileMode = 0b01000;
 // root節點,render方法接收的第二個參數
 this.containerInfo = containerInfo;  // 容器資訊
 // 隻有在持久更新中會用到,也就是不支援增量更新的平台,react-dom不會用到
 this.pendingChildren = null; // 持久化更新的資訊
 // 目前應用對應的Fiber對象,是Root Fiber
 this.current = null;  // root節點對應fiber 節點
 this.pingCache = null;
 
 // The earliest and latest priority levels that are suspended from committing.
 // 最老和新的在送出的時候被挂起的任務

 // 已經完成的任務的FiberRoot對象,如果你隻有一個Root,那他永遠隻可能是這個Root對應的Fiber,或者是null
 // 在commit階段隻會處理這個值對應的任務
 this.finishedWork = null;
 // 在任務被挂起的時候,通過setTimeout設定的傳回的内容
 // 用來下一次如果有新的任務挂起時, 清除沒有觸發的timeout

 // 在任務被挂起的時候通過setTimeout設定的傳回内容,用來下一次如果有新的任務挂起時清理還沒觸發的timeout
 this.timeoutHandle = noTimeout;  // -1
 // 頂層的context 對象, 隻有主動調用renderSubtreeIntoContainer 的時候才會用
 // 頂層context對象,隻有主動調用`renderSubtreeIntoContainer`時才會有用
 this.context = null;
 this.pendingContext = null;
 this.hydrate = hydrate;
 this.callbackNode = null;
 this.callbackPriority = NoLanePriority;  // 
 this.eventTimes = createLaneMap(NoLanes); // 31位的空的數組, 中間的值位 NoLanes: 0b0000000000000000000000000000000;
 this.expirationTimes = createLaneMap(NoTimestamp);  // 過期時間  -1
 this.pendingLanes = NoLanes;  //  0b0000000000000000000000000000000;
 this.suspendedLanes = NoLanes;  //  0b0000000000000000000000000000000;
 this.pingedLanes = NoLanes; // 0b0000000000000000000000000000000;
 this.expiredLanes = NoLanes;  // 過期的  0b0000000000000000000000000000000;
 this.mutableReadLanes = NoLanes;  //  0b0000000000000000000000000000000;
 this.finishedLanes = NoLanes;  // 完成的 0b0000000000000000000000000000000;
 this.entangledLanes = NoLanes; //  0b0000000000000000000000000000000;
 this.entanglements = createLaneMap(NoLanes);  // 0b0000000000000000000000000000000;
 // 支援Hrate
 
 if (supportsHydration) {
    this.mutableSourceEagerHydrationData = null;
  }
 // 能夠排程追蹤, 
 if (enableSchedulerTracing) {
    this.interactionThreadID = unstable_getThreadID();
   this.memoizedInteractions = new Set();
    this.pendingInteractionMap = new Map();
  }

 if (enableSuspenseCallback) {
     this.hydrationCallbacks = null;
 }
}
           

// createLaneMap 定義(12)

// 建立一個LaneMAp 
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiberLane.js
// 主題邏輯: 建立一個包含31個元素的數組, 值為傳入的參數
export function createLaneMap<T>(initial: T): LaneMap<T> {
 // Intentionally pushing one by one.
 // https://v8.dev/blog/elements-kinds#avoid-creating-holes
 // 空數組
 const laneMap = [];
 // 31
 for (let i = 0; i < TotalLanes; i++) {
 laneMap.push(initial);
  }
 return laneMap; // []
}
           

// createHostRootFiber 函數定義(13)

// 建立HostRootFiber 節點  tag : 0
代碼位置: src/react/packages/react-reconciler/src/ReactFiber.old.js
主題邏輯: 根據傳入的tag 确定mode , 調用建立rootFiber
export function createHostRootFiber(tag: RootTag): Fiber {
 // 模式定義
 
 let mode;
 // 當模式為ConcurrentMode m模式下
 if (tag === ConcurrentRoot) {
 // mode 增加嚴格, concurrent   
 mode = ConcurrentMode | BlockingMode | StrictMode;
 //  ConcurrentMode 模式 BlockingMode : 模式  StrictMode: 模式
  } else if (tag === BlockingRoot) {
 // Blocak   // 
 mode = BlockingMode | StrictMode;// BlockingMode 模式,  StrictMode 模式
  } else {
 // 沒有模式
    mode = NoMode;
  }

 if (enableProfilerTimer && isDevToolsPresent) {
    mode |= ProfileMode;
  }
 // 建立Fiber   // 比對模式
 return createFiber(HostRoot, null, null, mode);
 // HostRoot
}
           

// createFiber 函數定義 (14)

// 建立Fiber 節點的函數  // 建立HostRootFiber 節點
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiber.old.js
// 主題邏輯: 調用構造函數傳回rootFiber, tag 為3, 表示root 節點
// pendingProps  : null , key: null, tag: HostRoot
const createFiber = function(
 tag: WorkTag,
 pendingProps: mixed,  // {}
 key: null | string,  // 
 mode: TypeOfMode,
): Fiber {
 
 // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors
 // 建立的FiberNode節點
 return new FiberNode(tag, pendingProps, key, mode);
};
           

// FiberNode 構造函數 (15)

// FiberNode 的構造函數
// 代碼位置: src/react/packages/react-reconciler/src/ReactFiber.old.js
// 主體邏輯:  定義了構造函數
function FiberNode(
 tag: WorkTag,
 pendingProps: mixed,
 key: null | string,
 mode: TypeOfMode,
) {
 // Instance
 
 // 标記不同的元件類型
 this.tag = tag;  // 類型
 // ReactElement裡面的key
 this.key = key;  // key
 // ReactElement.type,也就是我們調用`createElement`的第一個參數
 this.elementType = null;
 // The resolved function/class/ associated with this fiber.
 // 異步元件resolved之後傳回的内容,一般是`function`或者`class`
 this.type = null;  // 類型
 // The local state associated with this fiber.
 // 跟目前Fiber相關本地狀态(比如浏覽器環境就是DOM節點)
 this.stateNode = null;  // dom 節點  // dom 執行個體或者class 執行個體

 // Fiber
 // 指向他在Fiber節點樹中的`parent`,用來在處理完這個節點之後向上傳回
 this.return = null;  // 傳回的結構
 // 單連結清單樹結構
 // 指向自己的第一個子節點
 this.child = null;  // 子節點
 // 指向自己的兄弟結構
 // 兄弟節點的return指向同一個父節點
 this.sibling = null;  // 兄弟節點
 this.index = 0;  // 下标, 記錄位置
 // ref屬性
 this.ref = null;    // ref  , 最後使用de shui
// 新的變動帶來的新的props
 this.pendingProps = pendingProps;  // 待更新props
 // 上一次渲染完成之後的props
 this.memoizedProps = null;  // 已經更新的props
 // 該Fiber對應的元件産生的Update會存放在這個隊列裡面
 this.updateQueue = null;  // 更新隊列
 // 上一次渲染的時候的state
 this.memoizedState = null;  // 更新的隊列
 this.dependencies = null;  // 同fiber 相關的context 事件
 // 處于什麼模式 concurerntMode  或者其他模式
 // 用來描述目前Fiber和他子樹的`Bitfield`
 // 共存的模式表示這個子樹是否預設是異步渲染的
 // Fiber被建立的時候他會繼承父Fiber
 // 其他的辨別也可以在建立的時候被設定
 // 但是在建立之後不應該再被修改,特别是他的子Fiber建立之前
 this.mode = mode;  // 受父節點控制

 // Effects
 // Effect
 // 用來記錄Side Effect
 this.flags = NoFlags;  // 副作用标示  PLACEMENT UPDATE , DELETE
 // 單連結清單用來快速查找下一個side effect
 this.nextEffect = null;
 // 子樹中第一個side effect
 this.firstEffect = null;  
 // 子樹中最後一個side effect
 this.lastEffect = null;
// 代表任務在未來的哪個時間點應該被完成
 // 不包括他的子樹産生的任務
 this.lanes = NoLanes;   // 過期事件, 二進制位
 // 快速确定子樹中是否有不在等待的變化
 this.childLanes = NoLanes;  // 子節點的
 // 在Fiber樹更新的過程中,每個Fiber都會有一個跟其對應的Fiber
 // 我們稱他為`current <==> workInProgress`
 // 在渲染完成之後他們會交換位置
 this.alternate = null;  // 指向舊的fiber
 // profiler 元件,計算react 的時間
 if (enableProfilerTimer) {

 this.actualDuration = Number.NaN;
 this.actualStartTime = Number.NaN;
 this.selfBaseDuration = Number.NaN;
 this.treeBaseDuration = Number.NaN;

 
 this.actualStartTime = -1;
 this.selfBaseDuration = 0;
 this.treeBaseDuration = 0;
  }
}
           

// initializeUpdateQueue 定義(16)

// 初始化更新隊列 fiber: uninitlialFiber rootFiber
// 代碼位置: src/react/packages/react-reconciler/src/ReactUpdateQueue.old.js
// 主題邏輯: 給rootFiber 中的updateQueue 增加一個初始的queue
export function initializeUpdateQueue<State>(fiber: Fiber): void {
 // 設定更新隊列
 
 // 設定更新隊列
 const queue: UpdateQueue<State> = {
 baseState: fiber.memoizedState,  // 原來的更新的基礎
 // 記錄資料結構, 開始
 firstBaseUpdate: null,  // 最開始BasUpdate
 // 記錄資料結構, 結束
 lastBaseUpdate: null,
 shared: {
 pending: null,
    },
 effects: null,  //   目前update 的副作用
  };
 //    更新隊列
 // rootFiber 中的updateQueue ,設定一個初始值
 fiber.updateQueue = queue;  // rootFiber 的updateQueue 設定更新
 // 給uninitlialFiber 
 // 設定rootFiber的更新隊列
}
           

// markContainerAsRoot 定義(17)

// hostRoot  fiberRoot.current   node: container
/// 定義markContainerAsRoot 
// 代碼位置: src/react/packages/react-dom/src/client/ReactDOMComponentTree.js
// 主題邏輯: 設定container.internalContainerInstanceKey 指向rootFiber
export function markContainerAsRoot(hostRoot: Fiber, node: Container): void {
 // container. internalContainerInstanceKey  = fiberRoot.current
 // 設定指向
 node[internalContainerInstanceKey] = hostRoot;
}
// 備注資訊: 
const randomKey = Math.random()
  .toString(36)
  .slice(2);
const internalContainerInstanceKey = '__reactContainer$' + randomKey;
           

// listenToAllSupportedEvents 定義(18)

// 當enableEagerRootListeners  對container 的元素的綁定
// rootContainerElement: container 
// 代碼位置: src/react/packages/react-dom/src/events/DOMPluginEventSystem.js
// 主題邏輯: 将觸發的事件綁定的container , 冒泡階段和觸發分别綁定
export function listenToAllSupportedEvents(rootContainerElement: EventTarget) {
 // ture
 if (enableEagerRootListeners) {
 // 初始為undefined
 if ((rootContainerElement: any)[listeningMarker]) {
      return;
    }
 // 初始false
    (rootContainerElement: any)[listeningMarker] = true;
 // 各種事件類型
 allNativeEvents.forEach(domEventName => {
 // 不進行冒泡代理的事件和  必須要綁定在指定元素的事件
 if (!nonDelegatedEvents.has(domEventName)) {
 //  冒泡階段的事件代理
   listenToNativeEvent(
     domEventName,  // 事件類型
    false,
    ((rootContainerElement: any): Element),
     null,
      );
      }
    // 在觸發階段的綁定
    listenToNativeEvent(
      domEventName,
     true,
     ((rootContainerElement: any): Element),
      null,
      );
    });
  }
}

// 備注
export const deferRenderPhaseUpdateToNextBatch = true;
           

流程圖

react回調函數_react源碼個人筆記-版本17.0.0(筆記02修改)

總結資訊:

1 通過ReactDom.render() 進行初始化流程, 再次更新的時候也可以通過ReactDom.render() 進行更新。

2 container.reactRootContainer 為一個ReactDOMBlockingRoot執行個體。執行個體的_internalRoot 為fiberRoot ,

3 建立rootFiber 對象, 設定rootFiber 與container 的關系,在遊覽器下設定部分事件挂載在container.

4 初始化queue 添加到rootFiber 的updateQueue上。