上文是建立了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;
};
复制代码
咱们先从 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,
);
}
复制代码
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;
}
复制代码
这个方法返回的对象和setState有关函数
function createUpdate(expirationTime: ExpirationTime): Update<*> {
return {
expirationTime: expirationTime,
tag: UpdateState,
// setState 的第一二个参数
payload: null,
callback: null,
// 用于在队列中找到下一个节点
next: null,
nextEffect: null,
};
}
复制代码
render的总体流程优化