React源碼學習筆記---render流程(2)

ReactRoot.prototype.render

上文是建立了root節點,這一篇是建立以後發生的事情數組

// batchedUpdate 是 React 中很重要的一步,也就是批量更新
    // this.setState({ age: 1 })
    // this.setState({ age: 2 })
    // this.setState({ age: 3 })
    // 以上三次 setState 會被優化成一次更新,減小了渲染次數
    // 可是對於 Root 來講不必批量更新,直接調用回調函數
    unbatchedUpdates(() => {
      // 上文中傳入的parentComponent爲null,因此直接進入render
      // 其實也不是沒可能存在 parentComponent,若是在 root 上使用 context 就能夠了
      if (parentComponent != null) {
        root.legacy_renderSubtreeIntoContainer(
          parentComponent,
          children,
          callback,
        );
      } else {
        // 調用的是 ReactRoot.prototype.render
        root.render(children, callback);
      }
    });
複製代碼
ReactRoot.prototype.render = function(
  children: ReactNodeList,
  callback: ?() => mixed,
): Work {
  // 這裏指 FiberRoot
  const root = this._internalRoot;
  // ReactWork 的功能就是爲了在組件渲染或更新後把全部傳入
  // ReactDom.render 中的回調函數所有執行一遍
  const work = new ReactWork();
  callback = callback === undefined ? null : callback;
  // 若是有 callback,就 push 進 work 中的數組
  if (callback !== null) {
    work.then(callback);
  }
  // work._onCommit 就是用於執行全部回調函數的
  updateContainer(children, root, null, work._onCommit);
  return work;
};
複製代碼

updateContainer

咱們先從 FiberRoot 的 current 屬性中取出它的 fiber 對象,而後計算了兩個時間。這兩個時間在 React 中至關重要。 只須要記住任務的過時時間是經過當前時間加上一個常量(任務優先級不一樣常量不一樣)計算出來的bash

function updateContainer(
  element: ReactNodeList,
  container: OpaqueRoot,
  parentComponent: ?React$Component<any, any>,
  callback: ?Function,
): ExpirationTime {
  // 取出容器的 fiber 對象,也就是 fiber root
  const current = container.current;
  // 計算時間
  const currentTime = requestCurrentTime();
  // expirationTime 表明優先級,數字越大優先級越高
  // sync 的數字是最大的,因此優先級也是最高的
  const expirationTime = computeExpirationForFiber(currentTime, current);
  
  // updateContainerAtExpirationTime這個函數直接返回scheduleRootUpdate,因此直接看它
  return updateContainerAtExpirationTime(
    element,
    container,
    parentComponent,
    expirationTime,
    callback,
  );
}
複製代碼

scheduleRootUpdate

function scheduleRootUpdate(
  current: Fiber,
  element: ReactNodeList,
  expirationTime: ExpirationTime,
  callback: ?Function,
) {
  // 建立一個 update,就是內部有幾個屬性的對象
  const update = createUpdate(expirationTime);
  // 第一次render直接將element當作payload    
  // being called "element".
  update.payload = {element};

  callback = callback === undefined ? null : callback;
  if (callback !== null) {
    update.callback = callback;
  }

  // 把 update 入隊,內部就是一些建立或者獲取 queue(鏈表結構),而後給鏈表添加一個節點的操做
  enqueueUpdate(current, update);
  // 調度相關
  scheduleWork(current, expirationTime);

  return expirationTime;
}
複製代碼

createUpdate

這個方法返回的對象和setState有關函數

function createUpdate(expirationTime: ExpirationTime): Update<*> {
  return {
    expirationTime: expirationTime,

    tag: UpdateState,
    // setState 的第一二個參數
    payload: null,
    callback: null,
    // 用於在隊列中找到下一個節點
    next: null,
    nextEffect: null,
  };
}
複製代碼

render的總體流程優化

相關文章
相關標籤/搜索