Skip to content

Commit 0908134

Browse files
committed
feat(reconciler): 完成 render 阶段源码注释以及调用栈图
1 parent de982c6 commit 0908134

21 files changed

+10492
-79
lines changed

docs/img/commit.dio

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

docs/img/render.dio

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

docs/img/test.dio

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

docs/render阶段/beginWork阶段/处理更新.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ this.setState({val: 6});
9898
结论是:这是因为方便定位到链表的第一个元素。updateQueue指向它的最后一个update,updateQueue.next指向它的第一个update。
9999

100100
试想一下,若不使用环状链表,updateQueue指向最后一个元素,需要遍历才能获取链表首部。即使将updateQueue指向第一个元素,那么新增update时仍然要遍历到尾部才能将新增的接入链表。而环状链表,只需记住尾部,无需遍历操作就可以找到首部。理解概念是重中之重,下面再来看一下实现:
101-
```
101+
``` js
102102
function enqueueUpdate<State>(fiber: Fiber, update: Update<State>) {
103103
const updateQueue = fiber.updateQueue;
104104
if (updateQueue === null) {

src/App.css

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
body{
2+
background-color: #0D1117;
3+
color: #ddd;
4+
}
15
#root {
26
position: relative;
37
}
@@ -7,8 +11,6 @@
711
position: absolute;
812
top: 20px;
913
left: 30%;
10-
} {
11-
1214
}
1315
.App {
1416
text-align: center;

src/App.js

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useEffect, useState, } from 'react';
2+
import ReactDOM from 'react-dom'
23
import State from './components/State'
34
import LanesDemo from './components/LanesDemo'
45
import AppSibling from './components/AppSibling'
@@ -22,41 +23,43 @@ function App() {
2223

2324
useEffect(() => {
2425
console.log('useEffect被执行');
26+
27+
console.log("%c'useEffect被执行 %c", "color:green",)
2528
return () => {
2629
console.log('useEffect 卸载函数被执行');
2730
}
2831
}, [])
2932

30-
const [count, setCount] = useState(1)
33+
const [flag, setFlag] = useState(true)
3134

3235
// 事件系统
3336
// return <EventDemo/>
3437

3538
// return <Hooks/>
3639
// fiber树
3740

38-
const a = <div>
39-
<h2 key="hello">hello</h2>
40-
<p key="world">world</p>
41-
</div>
42-
43-
// 顺序不一致
44-
// const b = <div>
45-
// <p key="world">world</p>
46-
// <h2 key="hello">hello</h2>
47-
// </div>
48-
49-
// 类型不一致
50-
const b = <div>
51-
<h6 key="hello">hello</h6>
52-
<p key="world">world</p>
53-
</div>
54-
5541
return (
56-
<div className="App" onClick={() => setCount(count + 1)}>
57-
{count % 2 ? a : b}
42+
<div className="App" onClick={() => {
43+
debugger;
44+
setFlag(!flag)
45+
}}>
46+
{
47+
flag
48+
? (
49+
<div>
50+
<h2 key="hello" className="h2-wrap">hello</h2>
51+
<p key="world" className="p-wrap">world</p>
52+
</div>
53+
)
54+
: (<div>
55+
<h6 key="hello">hello</h6>
56+
<p key="world">world</p>
57+
</div>)
58+
}
59+
5860
{/* <span>我是span {count}</span> */}
5961
{/* <h2>我是h2</h2> */}
62+
{/* {ReactDOM.createPortal} */}
6063
</div>
6164
);
6265
{/* <span className={'app-span'} onClick={() => setCount(count + 1)}>App{count}</span> */ }

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,8 @@ function legacyRenderSubtreeIntoContainer(
253253
// Update 批量更新
254254
updateContainer(children, fiberRoot, parentComponent, callback);
255255
}
256+
257+
// 获取根的真实dom
256258
return getPublicRootInstance(fiberRoot);
257259
}
258260

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ ReactDOMRoot.prototype.unmount = ReactDOMLegacyRoot.prototype.unmount = function
111111
});
112112
};
113113

114-
// 初始化rendr 时 options 的值是 { hydrate: true, } 和 undefined,非服务端渲染时是 undefined
114+
// legacy 模式 render() 初始化rendr 时 options 的值是 { hydrate: true, } 和 undefined,非服务端渲染时是 undefined
115115
function createRootImpl(
116116
container: Container,
117117
tag: RootTag,
@@ -176,6 +176,7 @@ function createRootImpl(
176176
return root;
177177
}
178178

179+
// concurrent 模式
179180
export function createRoot(
180181
container: Container,
181182
options?: RootOptions,

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
@@ -631,6 +631,7 @@ export function dispatchEventForPluginEventSystem(
631631
}
632632
}
633633

634+
// 批量更新
634635
batchedEventUpdates(() =>
635636
dispatchEventsForPlugins(
636637
domEventName,

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ function ChildReconciler(shouldTrackSideEffects) {
735735
lanes: Lanes,
736736
): Fiber | null {
737737

738-
// 这个算法不能通过从两端搜索来优化,因为我们在纤维上没有反向指针。我想看看这个模型能走多远。如果它最终不值得进行权衡,我们可以稍后添加它。
738+
// 这个算法不能通过从两端搜索来优化,因为我们在 fiber 上没有反向指针。我想看看这个模型能走多远。如果它最终不值得进行权衡,我们可以稍后添加它。
739739
// 即使是两个端点的优化,我们也希望优化的情况下,有很少的改变和暴力的比较,而不是去 Map。它会首先在forward-only模式中探索命中那条路径,并且只有当我们注意到我们需要很多前瞻性时才会去寻找 Map。这不能像两个结束的搜索那样处理反转,但这是不寻常的。此外,为了使两端优化在Iterables上工作,我们需要复制整个集合。
740740
// 在第一次迭代中,我们只会在每次插入/移动时碰到坏情况(向Map添加所有内容)。
741741
// 如果你改变这个代码,也更新reconcileChildrenIterator(),它使用相同的算法。
@@ -1110,6 +1110,7 @@ function ChildReconciler(shouldTrackSideEffects) {
11101110
): Fiber {
11111111
const key = element.key;
11121112
let child = currentFirstChild;
1113+
// 第一次 render child 为 null
11131114
while (child !== null) {
11141115
// TODO: If key === null and child.key === null, then this only applies to
11151116
// the first item in the list.
@@ -1327,9 +1328,7 @@ function ChildReconciler(shouldTrackSideEffects) {
13271328
}
13281329
}
13291330
if (typeof newChild === 'undefined' && !isUnkeyedTopLevelFragment) {
1330-
// If the new child is undefined, and the return fiber is a composite
1331-
// component, throw an error. If Fiber return types are disabled,
1332-
// we already threw above.
1331+
// If the new child is undefined, and the return fiber is a composite component, throw an error. If Fiber return types are disabled, we already threw above.
13331332
switch (returnFiber.tag) {
13341333
case ClassComponent: {
13351334
if (__DEV__) {

0 commit comments

Comments
 (0)