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的总体流程优化

相关文章
相关标签/搜索