上文是建立了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的總體流程優化