Skip to content

Commit 7c500a7

Browse files
committed
feat(reconciler): 新增调度阶段源码注释
1 parent 36be91b commit 7c500a7

12 files changed

+178
-32
lines changed

src/react/v17.0.2/react-dom/src/client/ReactDOMLegacy.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,18 +213,21 @@ function legacyRenderSubtreeIntoContainer(
213213
warnOnInvalidCallback(callback === undefined ? null : callback, 'render');
214214
}
215215

216-
// 第一次 render 的时候 _reactRootContainer 是空
216+
// 第一次 render 的时候 _reactRootContainer 是空
217217
let root = container._reactRootContainer;
218218
let fiberRoot: FiberRoot;
219219

220220
if (!root) {
221221
// Initial mount 初始化挂载,获取到 fiber 容器
222+
// 同时给 容器的 _reactRootContainer 赋上 fiberRoot 对象,下次进来就会走到 else
222223
root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
223224
container,
224225
forceHydrate,
225226
);
226227

227-
fiberRoot = root._internalRoot;
228+
// 因为 FiberRoot 实际是添加在 _internalRoot 身上的,所以要从 _internalRoot 身上取下来
229+
// 源码实现 ./ReactDOMRoot.js 中 ReactDOMLegacyRoot()
230+
fiberRoot = root._internalRoot;
228231

229232
if (typeof callback === 'function') {
230233
const originalCallback = callback;

src/react/v17.0.2/react-dom/src/client/ReactDOMRoot.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ function ReactDOMRoot(container: Container, options: void | RootOptions) {
5959
this._internalRoot = createRootImpl(container, ConcurrentRoot, options);
6060
}
6161

62+
// 刚方法是一个构造方法,给实例身上添加一个 _internalRoot 属性 ,fiberRoot 实际添加在 _internalRoot 身上
6263
function ReactDOMLegacyRoot(container: Container, options: void | RootOptions) {
6364
// export const LegacyRoot = 0; LegacyRoot 为 0
6465
this._internalRoot = createRootImpl(container, LegacyRoot, options);

src/react/v17.0.2/react-reconciler/src/ReactChildFiber.old.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ function ChildReconciler(shouldTrackSideEffects) {
350350
function placeSingleChild(newFiber: Fiber): Fiber {
351351
// This is simpler for the single child case. We only need to do a
352352
// placement for inserting new children.
353+
// 第一次 render 会进入判断
353354
if (shouldTrackSideEffects && newFiber.alternate === null) {
354355
newFiber.flags |= Placement;
355356
}
@@ -1090,6 +1091,7 @@ function ChildReconciler(shouldTrackSideEffects) {
10901091
return created;
10911092
}
10921093

1094+
// 调和单个元素
10931095
function reconcileSingleElement(
10941096
returnFiber: Fiber,
10951097
currentFirstChild: Fiber | null,
@@ -1161,8 +1163,11 @@ function ChildReconciler(shouldTrackSideEffects) {
11611163
created.return = returnFiber;
11621164
return created;
11631165
} else {
1166+
// 创建一个 fiber 对象
11641167
const created = createFiberFromElement(element, returnFiber.mode, lanes);
11651168
created.ref = coerceRef(returnFiber, currentFirstChild, element);
1169+
1170+
// 将该 fiber 对象的 rerurn 指向 父节点
11661171
created.return = returnFiber;
11671172
return created;
11681173
}
@@ -1233,6 +1238,9 @@ function ChildReconciler(shouldTrackSideEffects) {
12331238
// Handle object types
12341239
if (typeof newChild === 'object' && newChild !== null) {
12351240
switch (newChild.$$typeof) {
1241+
1242+
// 首次 render 时会进入到这里,通过createElement 创建的虚拟dom 都是 对象
1243+
// 先调和单个元素 ,会得到一个 当前元素的 fiber 对象
12361244
case REACT_ELEMENT_TYPE:
12371245
return placeSingleChild(
12381246
reconcileSingleElement(

src/react/v17.0.2/react-reconciler/src/ReactFiber.old.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,27 @@ function FiberNode(
121121
// Instance
122122
this.tag = tag;
123123
this.key = key;
124+
// createElement 时第一个参数 ,type
124125
this.elementType = null;
126+
127+
// 异步组件resolved之后返回的内容,一般是`function`或者`class`
125128
this.type = null;
129+
130+
// 对应的这个节点的真实 dom
126131
this.stateNode = null;
127132

128133
// Fiber
129-
this.return = null;
130-
this.child = null;
131-
this.sibling = null;
132-
this.index = 0;
134+
this.return = null; // 当前节点的 父节点
135+
this.child = null; // 当前节点的 子节点
136+
this.sibling = null; // 当前节点的 兄弟节点(后一个节点)
137+
this.index = 0; // 当前节点的 索引(用于更新时候的复用)
133138

134139
this.ref = null;
135140

136-
this.pendingProps = pendingProps;
137-
this.memoizedProps = null;
138-
this.updateQueue = null;
139-
this.memoizedState = null;
141+
this.pendingProps = pendingProps; // 新的 props
142+
this.memoizedProps = null; // 旧的(上一次) props
143+
this.updateQueue = null; // 当前 fiber 的更新队列
144+
this.memoizedState = null; // 旧的(上一次) state
140145
this.dependencies = null;
141146

142147
this.mode = mode;
@@ -149,6 +154,8 @@ function FiberNode(
149154
this.lanes = NoLanes;
150155
this.childLanes = NoLanes;
151156

157+
// 记录着上一次的 fiber
158+
// 每次渲染结束后 会交换位置, current《====》 alternate 不需要平凡
152159
this.alternate = null;
153160

154161
if (enableProfilerTimer) {
@@ -245,13 +252,24 @@ export function resolveLazyComponentTag(Component: Function): WorkTag {
245252

246253
// This is used to create an alternate fiber to do work on.
247254
export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
248-
let workInProgress = current.alternate;
255+
256+
// 先取到 旧的 alternate
257+
let workInProgress = current.alternate;
258+
259+
// 如果当前只有一个 fiber ,只有在第一次render 的时候才是 null
249260
if (workInProgress === null) {
250261
// We use a double buffering pooling technique because we know that we'll
251262
// only ever need at most two versions of a tree. We pool the "other" unused
252263
// node that we're free to reuse. This is lazily created to avoid allocating
253264
// extra objects for things that are never updated. It also allow us to
254265
// reclaim the extra memory if needed.
266+
// 这里会创建一个 fiber createFiber() 代码实现在以上
267+
/* 第一次 render 是
268+
3
269+
null
270+
null
271+
2
272+
*/
255273
workInProgress = createFiber(
256274
current.tag,
257275
pendingProps,
@@ -270,6 +288,7 @@ export function createWorkInProgress(current: Fiber, pendingProps: any): Fiber {
270288
workInProgress._debugHookTypes = current._debugHookTypes;
271289
}
272290

291+
// 指向自身
273292
workInProgress.alternate = current;
274293
current.alternate = workInProgress;
275294
} else {
@@ -471,12 +490,12 @@ export function createHostRootFiber(
471490
mode |= ProfileMode;
472491
}
473492

474-
// 开始创建
493+
// 开始创建一个 RootFiber
475494
return createFiber(HostRoot, null, null, mode);
476495
}
477496

478497
export function createFiberFromTypeAndProps(
479-
type: any, // React$ElementType
498+
type: any, // React$ElementType 类组件是 class 函数组件时 函数本身
480499
key: null | string,
481500
pendingProps: any,
482501
owner: null | Fiber,
@@ -487,6 +506,7 @@ export function createFiberFromTypeAndProps(
487506
// The resolved type is set if we know what the final type will be. I.e. it's not lazy.
488507
let resolvedType = type;
489508
if (typeof type === 'function') {
509+
// 判断是否 类组件
490510
if (shouldConstruct(type)) {
491511
fiberTag = ClassComponent;
492512
if (__DEV__) {
@@ -624,6 +644,8 @@ export function createFiberFromElement(
624644
const type = element.type;
625645
const key = element.key;
626646
const pendingProps = element.props;
647+
648+
// createFiberFromTypeAndProps() 方法实现就在以上
627649
const fiber = createFiberFromTypeAndProps(
628650
type,
629651
key,

src/react/v17.0.2/react-reconciler/src/ReactFiberBeginWork.old.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ export function reconcileChildren(
260260
// won't update its child set by applying minimal side-effects. Instead,
261261
// we will add them all to the child before it gets rendered. That means
262262
// we can optimize this reconciliation pass by not tracking side-effects.
263+
// 给 workInProgress 添加 child属性
263264
workInProgress.child = mountChildFibers(
264265
workInProgress,
265266
null,
@@ -273,6 +274,8 @@ export function reconcileChildren(
273274

274275
// If we had any progressed work already, that is invalid at this point so
275276
// let's throw it out.
277+
278+
// 将 workInProgress 的 child fiber 挂载到 .child 上
276279
workInProgress.child = reconcileChildFibers(
277280
workInProgress,
278281
current.child,
@@ -1138,7 +1141,9 @@ function pushHostRootContext(workInProgress) {
11381141
pushHostContainer(workInProgress, root.containerInfo);
11391142
}
11401143

1144+
// 更新根组件
11411145
function updateHostRoot(current, workInProgress, renderLanes) {
1146+
// 暂时没看
11421147
pushHostRootContext(workInProgress);
11431148
const updateQueue = workInProgress.updateQueue;
11441149
invariant(
@@ -1147,15 +1152,21 @@ function updateHostRoot(current, workInProgress, renderLanes) {
11471152
'bailed out. This error is likely caused by a bug in React. Please ' +
11481153
'file an issue.',
11491154
);
1155+
// 取到旧的 props 和 新的 props
11501156
const nextProps = workInProgress.pendingProps;
11511157
const prevState = workInProgress.memoizedState;
11521158
const prevChildren = prevState.element;
1159+
1160+
// 克隆更新队列
11531161
cloneUpdateQueue(current, workInProgress);
1162+
// 计算到新的 state
11541163
processUpdateQueue(workInProgress, nextProps, null, renderLanes);
1164+
// 取到新的 state
11551165
const nextState = workInProgress.memoizedState;
11561166

11571167
const root: FiberRoot = workInProgress.stateNode;
1158-
1168+
1169+
// 启用缓存, 暂时没看
11591170
if (enableCache) {
11601171
const nextCache: Cache = nextState.cache;
11611172
pushRootCachePool(root);
@@ -1173,6 +1184,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
11731184
resetHydrationState();
11741185
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
11751186
}
1187+
11761188
if (root.hydrate && enterHydrationState(workInProgress)) {
11771189
// If we don't have any current children this might be the first pass.
11781190
// We always try to hydrate. If this isn't a hydration pass there won't
@@ -1213,11 +1225,16 @@ function updateHostRoot(current, workInProgress, renderLanes) {
12131225
node = node.sibling;
12141226
}
12151227
} else {
1228+
// 第一次 render 进入到这里
12161229
// Otherwise reset hydration state in case we aborted and resumed another
12171230
// root.
1231+
// 调和 children
1232+
// 给 workInProgress 创建了 child
12181233
reconcileChildren(current, workInProgress, nextChildren, renderLanes);
12191234
resetHydrationState();
12201235
}
1236+
1237+
// 将 workInProgress 的 child 返回
12211238
return workInProgress.child;
12221239
}
12231240

@@ -1435,6 +1452,7 @@ function mountIncompleteClassComponent(
14351452
);
14361453
}
14371454

1455+
// 挂载不确定 tag 的组件
14381456
function mountIndeterminateComponent(
14391457
_current,
14401458
workInProgress,
@@ -1500,6 +1518,8 @@ function mountIndeterminateComponent(
15001518
);
15011519
setIsRendering(false);
15021520
} else {
1521+
// 第一次 render 时的 第二次循环 beginwork会进入到这里,因为 app 的类型不确定
1522+
// 得到函数式组件的 vdom
15031523
value = renderWithHooks(
15041524
null,
15051525
workInProgress,
@@ -1599,6 +1619,7 @@ function mountIndeterminateComponent(
15991619
);
16001620
} else {
16011621
// Proceed under the assumption that this is a function component
1622+
// 第一次 render 的第二次 循环会进入到这里 因为 app 组件的 chilren 还是一个 函数式组件
16021623
workInProgress.tag = FunctionComponent;
16031624
if (__DEV__) {
16041625
if (disableLegacyContext && Component.contextTypes) {
@@ -1628,10 +1649,14 @@ function mountIndeterminateComponent(
16281649
}
16291650
}
16301651
}
1652+
1653+
// 给 workInProgress 添加 child 属性内部再循环创建子的 fiber 对象
16311654
reconcileChildren(null, workInProgress, value, renderLanes);
16321655
if (__DEV__) {
16331656
validateFunctionComponentInDev(workInProgress, Component);
16341657
}
1658+
1659+
16351660
return workInProgress.child;
16361661
}
16371662
}
@@ -3222,9 +3247,11 @@ function beginWork(
32223247
}
32233248
}
32243249

3250+
// 取到 旧的 props 和新的 props
32253251
const oldProps = current.memoizedProps;
32263252
const newProps = workInProgress.pendingProps;
32273253

3254+
// 如果 props 或者 context 发生改变
32283255
if (
32293256
oldProps !== newProps ||
32303257
hasLegacyContextChanged() ||
@@ -3233,6 +3260,7 @@ function beginWork(
32333260
) {
32343261
// If props or context changed, mark the fiber as having performed work.
32353262
// This may be unset if the props are determined to be equal later (memo).
3263+
// 第一次 render 会进入这里
32363264
didReceiveUpdate = true;
32373265
} else if (!includesSomeLane(renderLanes, updateLanes)) {
32383266
didReceiveUpdate = false;
@@ -3472,7 +3500,11 @@ function beginWork(
34723500
// move this assignment out of the common path and into each branch.
34733501
workInProgress.lanes = NoLanes;
34743502

3503+
debugger;
3504+
3505+
// 判断是哪一个 tag 类型
34753506
switch (workInProgress.tag) {
3507+
// 不确定的 tag 类型
34763508
case IndeterminateComponent: {
34773509
return mountIndeterminateComponent(
34783510
current,
@@ -3521,7 +3553,7 @@ function beginWork(
35213553
renderLanes,
35223554
);
35233555
}
3524-
case HostRoot:
3556+
case HostRoot: //root 组件 会返回 workInProgress.child;
35253557
return updateHostRoot(current, workInProgress, renderLanes);
35263558
case HostComponent:
35273559
return updateHostComponent(current, workInProgress, renderLanes);

src/react/v17.0.2/react-reconciler/src/ReactFiberHooks.old.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,12 +402,14 @@ export function renderWithHooks<Props, SecondArg>(
402402
ReactCurrentDispatcher.current = HooksDispatcherOnMountInDEV;
403403
}
404404
} else {
405+
// current = null 会 取到 HooksDispatcherOnMount
405406
ReactCurrentDispatcher.current =
406407
current === null || current.memoizedState === null
407408
? HooksDispatcherOnMount
408409
: HooksDispatcherOnUpdate;
409410
}
410411

412+
// 调用函数式组件 传入 props 取到 renturn 的结果 函数式组件的 vdom
411413
let children = Component(props, secondArg);
412414

413415
// Check if there was a render phase update
@@ -523,7 +525,7 @@ export function renderWithHooks<Props, SecondArg>(
523525
}
524526
}
525527
}
526-
528+
// 将 children 返回 / 函数式组件的 vdom
527529
return children;
528530
}
529531

src/react/v17.0.2/react-reconciler/src/ReactFiberLane.old.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,14 +245,16 @@ function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {
245245

246246
export function getNextLanes(root: FiberRoot, wipLanes: Lanes): Lanes {
247247
// Early bailout if there's no pending work left.
248-
const pendingLanes = root.pendingLanes;
249-
if (pendingLanes === NoLanes) {
250-
return_highestLanePriority = NoLanePriority;
248+
249+
// 第一次是 1
250+
const pendingLanes = root.pendingLanes;
251+
if (pendingLanes === NoLanes) {
252+
return_highestLanePriority = NoLanePriority;
251253
return NoLanes;
252254
}
253255

254-
let nextLanes = NoLanes;
255-
let nextLanePriority = NoLanePriority;
256+
let nextLanes = NoLanes; // 0b0000000000000000000000000000000
257+
let nextLanePriority = NoLanePriority; // 0
256258

257259
const suspendedLanes = root.suspendedLanes;
258260
const pingedLanes = root.pingedLanes;
@@ -676,6 +678,11 @@ export function markRootUpdated(
676678
}
677679

678680
// 31 个时间戳
681+
/*
682+
* 假设 lanes:0b000100
683+
* 那么eventTimes是这种形式: [ -1, -1, -1, 44573.3452, -1, -1 ]
684+
* 用一个数组去存储eventTimes,-1表示空位,非-1的位置与lanes中的1的位置相同
685+
* */
679686
const eventTimes = root.eventTimes;
680687
// 根据 更新等级返回 索引
681688
const index = laneToIndex(updateLane);

0 commit comments

Comments
 (0)