-
Notifications
You must be signed in to change notification settings - Fork 20
/
fiber.js
135 lines (121 loc) · 3.91 KB
/
fiber.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import { renderDom } from './react-dom';
import { commitRoot } from './commit';
import { reconcileChildren } from './reconciler';
let nextUnitOfWork = null;
let workInProgressRoot = null; // 当前工作的 fiber 树
let currentRoot = null; // 上一次渲染的 fiber 树
let deletions = []; // 要执行删除 dom 的 fiber
// 将某个 fiber 加入 deletions 数组
export function deleteFiber(fiber) {
deletions.push(fiber);
}
// 获取 deletions 数组
export function getDeletions() {
return deletions;
}
// 触发渲染
export function commitRender() {
workInProgressRoot = {
stateNode: currentRoot.stateNode, // 记录对应的真实 dom 节点
element: currentRoot.element,
alternate: currentRoot,
};
nextUnitOfWork = workInProgressRoot;
}
// 创建 rootFiber 作为首个 nextUnitOfWork
export function createRoot(element, container) {
workInProgressRoot = {
stateNode: container, // 记录对应的真实 dom 节点
element: {
// 挂载 element
props: { children: [element] },
},
alternate: currentRoot,
};
nextUnitOfWork = workInProgressRoot;
}
// 执行当前工作单元并设置下一个要执行的工作单元
function performUnitOfWork(workInProgress) {
if (!workInProgress.stateNode) {
// 若当前 fiber 没有 stateNode,则根据 fiber 挂载的 element 的属性创建
workInProgress.stateNode = renderDom(workInProgress.element);
}
let children = workInProgress.element?.props?.children;
let type = workInProgress.element?.type;
if (typeof type === 'function') {
// 当前 fiber 对应 React 组件时,对其 return 迭代
if (type.prototype.isReactComponent) {
// 类组件
updateClassComponent(workInProgress);
} else {
// 函数组件
const { props, type: Fn } = workInProgress.element;
const jsx = Fn(props);
children = [jsx];
}
}
if (children || children === 0) {
// children 存在时,对 children 迭代
let elements = Array.isArray(children) ? children : [children];
// 打平列表渲染时二维数组的情况(暂不考虑三维及以上数组的情形)
elements = elements.flat();
reconcileChildren(workInProgress, elements);
}
// 设置下一个工作单元
if (workInProgress.child) {
// 如果有子 fiber,则下一个工作单元是子 fiber
nextUnitOfWork = workInProgress.child;
} else {
let nextFiber = workInProgress;
while (nextFiber) {
if (nextFiber.sibling) {
// 没有子 fiber 有兄弟 fiber,则下一个工作单元是兄弟 fiber
nextUnitOfWork = nextFiber.sibling;
return;
} else {
// 子 fiber 和兄弟 fiber 都没有,深度优先遍历返回上一层
nextFiber = nextFiber.return;
}
}
if (!nextFiber) {
// 若返回最顶层,表示迭代结束,将 nextUnitOfWork 置空
nextUnitOfWork = null;
}
}
}
// 类组件的更新
function updateClassComponent(fiber) {
let jsx;
if (fiber.alternate) {
// 有旧组件,复用
const component = fiber.alternate.component;
fiber.component = component;
component._UpdateProps(fiber.element.props);
jsx = component.render();
} else {
// 没有则创建新组件
const { props, type: Comp } = fiber.element;
const component = new Comp(props);
fiber.component = component;
jsx = component.render();
}
reconcileChildren(fiber, [jsx]);
}
// 处理循环和中断逻辑
function workLoop(deadline) {
let shouldYield = false;
while (nextUnitOfWork && !shouldYield) {
// 循环执行工作单元任务
performUnitOfWork(nextUnitOfWork);
shouldYield = deadline.timeRemaining() < 1;
}
if (!nextUnitOfWork && workInProgressRoot) {
// 表示进入 commit 阶段
commitRoot(workInProgressRoot);
currentRoot = workInProgressRoot;
workInProgressRoot = null;
deletions = [];
}
requestIdleCallback(workLoop);
}
requestIdleCallback(workLoop);