1
1
{
2
2
"postDataMap" : {
3
3
"first" : {
4
- "authors" : [" zhw" ],
4
+ "authors" : [
5
+ " zhw"
6
+ ],
5
7
"title" : " 建站" ,
6
8
"tag" : " 生活" ,
7
9
"path" : " first" ,
8
10
"rawFilePath" : " ./first.md" ,
9
11
"coverImage" : " https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg" ,
10
- "text" : " 记录一下建站的第一天,也许开心到爆炸.\r\n \r\n " ,
12
+ "text" : " 记录一下建站的第一天,也许开心到爆炸.\r\n \r\n \r\n " ,
11
13
"count" : " 268" ,
12
14
"readingTime" : " 1 " ,
13
15
"imageUrls" : [
14
16
" https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg" ,
15
17
" https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif"
16
18
],
17
19
"createdAt" : " 2024-11-13T12:48:31.000Z" ,
18
- "updatedAt" : " 2024-11-13T13:01:51 .000Z" ,
20
+ "updatedAt" : " 2024-11-14T08:12:55 .000Z" ,
19
21
"modified" : true
22
+ },
23
+ "react-scan" : {
24
+ "authors" : [
25
+ " zhw"
26
+ ],
27
+ "title" : " 聊聊react-scan" ,
28
+ "tag" : " react" ,
29
+ "path" : " react-scan" ,
30
+ "rawFilePath" : " ./react-scan.md" ,
31
+ "coverImage" : " https://raw.githubusercontent.com/aidenybai/react-scan/ca7746e2808408c04bcfbfc15486368e67d72bba/.github/assets/logo.svg" ,
32
+ "text": "# react - scan 核心原理剖析\r\n\r\nreact - scan 是一个用于监听react重渲染的工具,其核心原理是巧妙伪装成 React DevTools,借此成功接入 React 的内部运行机制,从而精准获取 Fiber 节点关键信息,实现对组件更新状况的实时监控。\r\n\r\nReact DevTools 在网页的 window 对象上会挂载一个特殊的全局对象:`__REACT_DEVTOOLS_GLOBAL_HOOK__`。React 在自身运行期间,于某些关键生命周期节点,会调用这个对象上的指定方法,像在 commit 阶段就会调用 `onCommitFiberRoot` 方法,并向其传入当前更新的 FiberRoot 节点作为参数。\r\n\r\nreact - scan 则利用这一点,通过劫持该 hook 上的函数,例如对 `onCommitFiberRoot` 进行重写操作,从而顺利获取整个 React 应用的 Fiber 树根节点。获取根节点后,借助 Fiber 节点的 child 属性指向第一个子节点、sibling 属性指向下一个兄弟节点,就能递归遍历整棵 Fiber 树,进而拿到每一个组件对应的 Fiber 节点详细信息。\r\n\r\n**如何判断组件是否发生更新?**\r\n\r\n * 对于非 Host 组件(即非原生 DOM 节点):通过位运算判断其 flags 与 PerformedWork 相与的结果是否为 PerformedWork,以此确定该 Fiber 节点是否发生更新。\r\n * 对于 Host 组件(对应实际 DOM 节点):\r\n * 若不存在 alternate 节点,表明是组件的首次渲染(因为 Fiber 采用双缓冲机制,存在当前树与上一次树之分)。\r\n * 若存在 alternate 节点,则对比当前与上一次的 memoizedProps(组件属性)、memoizedState(组件状态)、ref,判断组件是否更新。\r\n\r\n**如何定位更新组件的 DOM 元素?**\r\n\r\n一旦确定组件发生更新,可以从对应的 Fiber 节点向上查找最近的 Host 节点(即 Host Fiber),获取其关联的 DOM 元素,进而对 DOM 元素进行高亮或标记操作,方便进行调试或可视化展示。\r\n\r\n**一些其他功能:**\r\n\r\n * 对比两棵 Fiber 树的 memoizedProps,能够精确知晓具体哪个 prop 发生了变化。\r\n * 判断是否因 Context 变化引发的组件更新:可通过 fiber.firstContext 获取组件订阅的第一个 Context,然后凭借其 next 属性依次遍历所有订阅的 Context 节点,查找更新源头。\r\n * 判断是否因为 Hook 更新导致组件更新:鉴于 Fiber 上的 memoizedState 存储着 hooks 链表,可据此分析是哪个 state 发生了变化。",
33
+ "count" : " 1.1k" ,
34
+ "readingTime" : " 5 " ,
35
+ "imageUrls" : [],
36
+ "createdAt" : null ,
37
+ "updatedAt" : null ,
38
+ "modified" : false
20
39
}
21
40
},
22
41
"postDataList" : [
23
42
{
24
- "authors" : [" zhw" ],
43
+ "authors" : [
44
+ " zhw"
45
+ ],
25
46
"title" : " 建站" ,
26
47
"tag" : " 生活" ,
27
48
"path" : " first" ,
28
49
"rawFilePath" : " ./first.md" ,
29
50
"coverImage" : " https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg" ,
30
- "text" : " 记录一下建站的第一天,也许开心到爆炸.\r\n \r\n " ,
51
+ "text" : " 记录一下建站的第一天,也许开心到爆炸.\r\n \r\n \r\n " ,
31
52
"count" : " 268" ,
32
53
"readingTime" : " 1 " ,
33
54
"imageUrls" : [
34
55
" https://upload-bbs.miyoushe.com/upload/2024/07/27/75276539/98580c852764d70e5a9597aa7678f131_2245446554692880272.jpg" ,
35
56
" https://upload-bbs.miyoushe.com/upload/2024/03/20/285532152/757fa74f8b38fdfab0bd1b653a69af4d_6553329811603610700.gif"
36
57
],
37
58
"createdAt" : " 2024-11-13T12:48:31.000Z" ,
38
- "updatedAt" : " 2024-11-13T13:01:51 .000Z" ,
59
+ "updatedAt" : " 2024-11-14T08:12:55 .000Z" ,
39
60
"modified" : true
61
+ },
62
+ {
63
+ "authors" : [
64
+ " zhw"
65
+ ],
66
+ "title" : " 聊聊react-scan" ,
67
+ "tag" : " react" ,
68
+ "path" : " react-scan" ,
69
+ "rawFilePath" : " ./react-scan.md" ,
70
+ "coverImage" : " https://raw.githubusercontent.com/aidenybai/react-scan/ca7746e2808408c04bcfbfc15486368e67d72bba/.github/assets/logo.svg" ,
71
+ "text": "# react - scan 核心原理剖析\r\n\r\nreact - scan 是一个用于监听react重渲染的工具,其核心原理是巧妙伪装成 React DevTools,借此成功接入 React 的内部运行机制,从而精准获取 Fiber 节点关键信息,实现对组件更新状况的实时监控。\r\n\r\nReact DevTools 在网页的 window 对象上会挂载一个特殊的全局对象:`__REACT_DEVTOOLS_GLOBAL_HOOK__`。React 在自身运行期间,于某些关键生命周期节点,会调用这个对象上的指定方法,像在 commit 阶段就会调用 `onCommitFiberRoot` 方法,并向其传入当前更新的 FiberRoot 节点作为参数。\r\n\r\nreact - scan 则利用这一点,通过劫持该 hook 上的函数,例如对 `onCommitFiberRoot` 进行重写操作,从而顺利获取整个 React 应用的 Fiber 树根节点。获取根节点后,借助 Fiber 节点的 child 属性指向第一个子节点、sibling 属性指向下一个兄弟节点,就能递归遍历整棵 Fiber 树,进而拿到每一个组件对应的 Fiber 节点详细信息。\r\n\r\n**如何判断组件是否发生更新?**\r\n\r\n * 对于非 Host 组件(即非原生 DOM 节点):通过位运算判断其 flags 与 PerformedWork 相与的结果是否为 PerformedWork,以此确定该 Fiber 节点是否发生更新。\r\n * 对于 Host 组件(对应实际 DOM 节点):\r\n * 若不存在 alternate 节点,表明是组件的首次渲染(因为 Fiber 采用双缓冲机制,存在当前树与上一次树之分)。\r\n * 若存在 alternate 节点,则对比当前与上一次的 memoizedProps(组件属性)、memoizedState(组件状态)、ref,判断组件是否更新。\r\n\r\n**如何定位更新组件的 DOM 元素?**\r\n\r\n一旦确定组件发生更新,可以从对应的 Fiber 节点向上查找最近的 Host 节点(即 Host Fiber),获取其关联的 DOM 元素,进而对 DOM 元素进行高亮或标记操作,方便进行调试或可视化展示。\r\n\r\n**一些其他功能:**\r\n\r\n * 对比两棵 Fiber 树的 memoizedProps,能够精确知晓具体哪个 prop 发生了变化。\r\n * 判断是否因 Context 变化引发的组件更新:可通过 fiber.firstContext 获取组件订阅的第一个 Context,然后凭借其 next 属性依次遍历所有订阅的 Context 节点,查找更新源头。\r\n * 判断是否因为 Hook 更新导致组件更新:鉴于 Fiber 上的 memoizedState 存储着 hooks 链表,可据此分析是哪个 state 发生了变化。",
72
+ "count" : " 1.1k" ,
73
+ "readingTime" : " 5 " ,
74
+ "imageUrls" : [],
75
+ "createdAt" : null ,
76
+ "updatedAt" : null ,
77
+ "modified" : false
40
78
}
41
79
]
42
- }
80
+ }
0 commit comments