Skip to content

Commit adcc701

Browse files
committed
feat(react-reconciler): 完成 beginWork 源码注释
1 parent 7c500a7 commit adcc701

19 files changed

+621
-30
lines changed

README-ME.md

Lines changed: 490 additions & 0 deletions
Large diffs are not rendered by default.

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,13 @@ function getOwnerDocumentFromRootContainer(
254254
function noop() {}
255255

256256
export function trapClickOnNonInteractiveElement(node: HTMLElement) {
257+
258+
// Mobile Safari不会正确地在非交互式元素上触发冒泡单击事件,这意味着委托的单击侦听器不会触发。
259+
// 此bug的解决方案包括在目标节点上附加一个空的单击侦听器。
260+
// https://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
261+
// 只需使用onclick属性设置它,这样我们就不必为它管理任何簿记。不确定侦听器被删除时是否需要清除它。
262+
// TODO:只有相关的游猎才能这样做?
263+
257264
// Mobile Safari does not fire properly bubble click events on
258265
// non-interactive elements, which means delegated click listeners do not
259266
// fire. The workaround for this bug involves attaching an empty click
@@ -353,14 +360,16 @@ function updateDOMProperties(
353360
}
354361
}
355362

363+
// 开始使用 虚拟 dom 创建真实 dom
356364
export function createElement(
357365
type: string,
358366
props: Object,
359367
rootContainerElement: Element | Document,
360368
parentNamespace: string,
361369
): Element {
362-
let isCustomComponentTag;
370+
let isCustomComponentTag; // 是否自定义标签
363371

372+
// 拿到 document 对象
364373
// We create tags in the namespace of their parent container, except HTML
365374
// tags get no namespace.
366375
const ownerDocument: Document = getOwnerDocumentFromRootContainer(
@@ -412,6 +421,8 @@ export function createElement(
412421
// Separate else branch instead of using `props.is || undefined` above because of a Firefox bug.
413422
// See discussion in https://github.com/facebook/react/pull/6896
414423
// and discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1276240
424+
425+
// 通过 document 对象创建 真实dom
415426
domElement = ownerDocument.createElement(type);
416427
// Normally attributes are assigned in `setInitialDOMProperties`, however the `multiple` and `size`
417428
// attributes on `select`s needs to be added before `option`s are inserted.
@@ -585,6 +596,8 @@ export function setInitialProperties(
585596
ReactDOMSelectPostMountWrapper(domElement, rawProps);
586597
break;
587598
default:
599+
600+
// 以下是为了兼容 Safari 浏览器在 非交互元素上不会触发冒泡事件做的空 onClick 的兼容
588601
if (typeof props.onClick === 'function') {
589602
// TODO: This cast may not be sound for SVG, MathML or custom elements.
590603
trapClickOnNonInteractiveElement(((domElement: any): HTMLElement));

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {getParentSuspenseInstance} from './ReactDOMHostConfig';
3333
import invariant from 'shared/invariant';
3434
import {enableScopeAPI} from 'shared/ReactFeatureFlags';
3535

36+
// 取一个 0-1 的随机数,再转成 36 进制(a-z 0-9),再去掉前两位小数 0.2i116qjpu7p 一般是为了去重
3637
const randomKey = Math.random()
3738
.toString(36)
3839
.slice(2);
@@ -53,6 +54,7 @@ export function detachDeletedInstance(node: Instance): void {
5354
delete (node: any)[internalEventHandlesSetKey];
5455
}
5556

57+
// 给真实 dom 身上添加一个fiber 2i116qjpu7p 它的值是 fiber 虚拟dom
5658
export function precacheFiberNode(
5759
hostInst: Fiber,
5860
node: Instance | TextInstance | SuspenseInstance | ReactScopeInstance,
@@ -199,6 +201,10 @@ export function getFiberCurrentPropsFromNode(
199201
return (node: any)[internalPropsKey] || null;
200202
}
201203

204+
// 给真实 dom 身上添加props "__reactProps$2i116qjpu7p" 它的值是 这个元素身上的 props,
205+
// children: "你好呀"
206+
// className: "theme-context-child"
207+
// style: {background: "purple"}
202208
export function updateFiberProps(
203209
node: Instance | TextInstance | SuspenseInstance,
204210
props: Props,

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ const STYLE = 'style';
152152
let eventsEnabled: ?boolean = null;
153153
let selectionInformation: null | SelectionInformation = null;
154154

155+
156+
// 判断是否为以下几个元素,并且 props 中是否添加了自动聚焦属性,
155157
function shouldAutoFocusHostComponent(type: string, props: Props): boolean {
156158
switch (type) {
157159
case 'button':
@@ -260,6 +262,7 @@ export function resetAfterCommit(containerInfo: Container): void {
260262
selectionInformation = null;
261263
}
262264

265+
// 创建实例 创建元素实体
263266
export function createInstance(
264267
type: string,
265268
props: Props,
@@ -287,13 +290,17 @@ export function createInstance(
287290
} else {
288291
parentNamespace = ((hostContext: any): HostContextProd);
289292
}
293+
294+
// 创建元素
290295
const domElement: Instance = createElement(
291296
type,
292297
props,
293298
rootContainerInstance,
294299
parentNamespace,
295300
);
301+
// 给真实dom 身上添加 fiber 对象 domElement["__reactFiber$2i116qjpu7p"] = internalInstanceHandle
296302
precacheFiberNode(internalInstanceHandle, domElement);
303+
// 给真实dom 身上添加 props 对象 domElement["__reactProps$2i116qjpu7p"] = { children: '你好呀', className: 'theme-context-child' }
297304
updateFiberProps(domElement, props);
298305
return domElement;
299306
}
@@ -313,6 +320,7 @@ export function finalizeInitialChildren(
313320
hostContext: HostContext,
314321
): boolean {
315322
setInitialProperties(domElement, type, props, rootContainerInstance);
323+
//
316324
return shouldAutoFocusHostComponent(type, props);
317325
}
318326

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,18 @@ function createRootImpl(
152152
concurrentUpdatesByDefaultOverride,
153153
);
154154

155-
/* 将该容器标记为根, 内部是给容器身上添加一个一个随机数属性
155+
/*
156+
将该容器标记为根, 内部是给容器身上添加一个一个随机数属性
157+
container.__reactContainer$83ljcj61lpa = root.current
156158
node[internalContainerInstanceKey] = hostRoot;
157159
container[__reactContainer$+Math.random().toString(36).slice(2)] = root.current;
158160
*/
159161
markContainerAsRoot(root.current, container);
160162

163+
// 判断容器的节点类型是否为注释,如果是则使用父容器作为容器,否则就使用容器本身
161164
const rootContainerElement =
162165
container.nodeType === COMMENT_NODE ? container.parentNode : container;
166+
// 监听所有事件
163167
listenToAllSupportedEvents(rootContainerElement);
164168

165169
if (mutableSources) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const setTextContent = function(node: Element, text: string): void {
3131
return;
3232
}
3333
}
34+
// react 内部设置文本的方式
3435
node.textContent = text;
3536
};
3637

src/react/v17.0.2/react-dom/src/events/DOMPluginEventSystem.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ const listeningMarker =
381381
.toString(36)
382382
.slice(2);
383383

384+
// 开始监听所有事件
384385
export function listenToAllSupportedEvents(rootContainerElement: EventTarget) {
385386
if (!(rootContainerElement: any)[listeningMarker]) {
386387
(rootContainerElement: any)[listeningMarker] = true;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,9 @@ function ChildReconciler(shouldTrackSideEffects) {
12051205
}
12061206

12071207
const created = createFiberFromPortal(portal, returnFiber.mode, lanes);
1208+
// 给该 fiber 对象的 return 属性指向父 fiber 节点
1209+
// 传入的是 workInProgress,
1210+
// 该 created 会 作为 workInProgress.child 的属性(这就是 react fiber 链表)
12081211
created.return = returnFiber;
12091212
return created;
12101213
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ function FiberNode(
141141
this.pendingProps = pendingProps; // 新的 props
142142
this.memoizedProps = null; // 旧的(上一次) props
143143
this.updateQueue = null; // 当前 fiber 的更新队列
144-
this.memoizedState = null; // 旧的(上一次) state
144+
this.memoizedState = null; // 旧的(上一次) state 里面有缓存,react 使用的是 Map 作为缓存
145145
this.dependencies = null;
146146

147147
this.mode = mode;
@@ -620,6 +620,8 @@ export function createFiberFromTypeAndProps(
620620
}
621621
}
622622

623+
// 给 当前元素创建一个 fiber 对象
624+
// 例如 给 app 创建
623625
const fiber = createFiber(fiberTag, pendingProps, key, mode);
624626
fiber.elementType = type;
625627
fiber.type = resolvedType;

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ if (__DEV__) {
249249
didWarnAboutDefaultPropsOnFunctionComponent = {};
250250
}
251251

252+
// 调和 children
252253
export function reconcileChildren(
253254
current: Fiber | null,
254255
workInProgress: Fiber,
@@ -1157,9 +1158,10 @@ function updateHostRoot(current, workInProgress, renderLanes) {
11571158
const prevState = workInProgress.memoizedState;
11581159
const prevChildren = prevState.element;
11591160

1161+
debugger;
11601162
// 克隆更新队列
11611163
cloneUpdateQueue(current, workInProgress);
1162-
// 计算到新的 state
1164+
// 计算到新的 state 给 memoizedState 添加上值 cache,element
11631165
processUpdateQueue(workInProgress, nextProps, null, renderLanes);
11641166
// 取到新的 state
11651167
const nextState = workInProgress.memoizedState;
@@ -1168,6 +1170,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
11681170

11691171
// 启用缓存, 暂时没看
11701172
if (enableCache) {
1173+
// 拿到缓存
11711174
const nextCache: Cache = nextState.cache;
11721175
pushRootCachePool(root);
11731176
pushCacheProvider(workInProgress, nextCache);
@@ -1254,8 +1257,11 @@ function updateHostComponent(
12541257
const prevProps = current !== null ? current.memoizedProps : null;
12551258

12561259
let nextChildren = nextProps.children;
1260+
1261+
// 是否只有一个文本子节点
12571262
const isDirectTextChild = shouldSetTextContent(type, nextProps);
12581263

1264+
// 如果只有一个文本子节点,则不会给给文本子节点生成 fiber 节点
12591265
if (isDirectTextChild) {
12601266
// We special case a direct text child of a host node. This is a common
12611267
// case. We won't handle it as a reified child. We will instead handle
@@ -3500,7 +3506,7 @@ function beginWork(
35003506
// move this assignment out of the common path and into each branch.
35013507
workInProgress.lanes = NoLanes;
35023508

3503-
debugger;
3509+
// debugger;
35043510

35053511
// 判断是哪一个 tag 类型
35063512
switch (workInProgress.tag) {

0 commit comments

Comments
 (0)