Skip to content

Commit 0109575

Browse files
committed
feat: 完善核心模块设计 Reconciler 架构 递归创建Fiber树
1 parent a81254a commit 0109575

File tree

16 files changed

+675
-0
lines changed

16 files changed

+675
-0
lines changed
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# 📖 2.JSX转换 - 学习总结
2+
3+
> **生成时间**: 2025-10-17 02:08:41
4+
> **原笔记**: notes-react/notes/2.JSX转换.md
5+
6+
## 🎯 学习主题
7+
8+
本次学习的核心主题是 **React JSX 转换机制**,重点深入理解了 JSX 从编译时到运行时的完整转换流程,特别是 React 17+ 新版 JSX 转换规范的实际实现。
9+
10+
## 🔧 技术要点
11+
12+
### 1. JSX 转换的双阶段架构
13+
14+
**编译时(Babel 处理)**
15+
- **词法分析**:将 JSX 代码拆分为 Token 流(标签、属性、文本等)
16+
- **语法分析**:构建抽象语法树(AST),处理嵌套结构和动态表达式
17+
- **代码生成**:根据 React 版本生成不同的函数调用格式
18+
19+
**运行时(React 处理)**
20+
- 执行 `jsx()``React.createElement()` 函数
21+
- 创建虚拟 DOM 对象(React Element)
22+
- 构建虚拟 DOM 树并进行 Diff 计算
23+
24+
### 2. React 17+ JSX 转换的重大变化
25+
26+
通过代码实现,深刻理解了新旧版本的差异:
27+
28+
**React 17 前**
29+
```javascript
30+
// 需要手动引入 React
31+
React.createElement('div',
32+
null,
33+
'hello',
34+
React.createElement('span', null, 'world')
35+
)
36+
```
37+
38+
**React 17+**
39+
```javascript
40+
// 自动导入 jsx-runtime
41+
import { jsx as _jsx } from 'react/jsx-runtime';
42+
jsx('div', {
43+
children: ['hello', jsx('span', { children: 'world' })]
44+
})
45+
```
46+
47+
### 3. 核心代码实现逻辑
48+
49+
**React Element 工厂函数**
50+
```typescript
51+
const ReactElement = function(type: ElementType, key: Key, ref: Ref, props: Props) {
52+
return {
53+
$$typeof: REACT_ELEMENT_TYPE,
54+
type, // 元素类型
55+
key, // 元素 key
56+
ref, // 元素引用
57+
props, // 元素属性
58+
_mark: '_juanlou' // 调试标记
59+
};
60+
};
61+
```
62+
63+
**JSX 函数的关键改进**
64+
- **参数简化**:从 `jsx(type, config, ...maybeChildren)` 改为 `jsx(type, config)`
65+
- **子元素处理**:移除了手动处理 children 的逻辑,改为通过 config.children 传递
66+
- **属性提取**:统一从 config 对象中提取 key、ref 和其他 props
67+
68+
### 4. 模块化打包架构
69+
70+
通过 Rollup 配置实现了完整的模块打包:
71+
- **UMD 格式**:支持浏览器和 Node.js 环境
72+
- **自动生成 package.json**:根据源码包信息动态生成
73+
- **多入口打包**:分别打包 `react``jsx-runtime``jsx-dev-runtime`
74+
75+
## 💡 深度理解
76+
77+
### 1. JSX 转换的设计哲学演进
78+
79+
通过实现过程,深刻理解了 React 团队为什么要引入新的 JSX 转换:
80+
81+
**Tree-shaking 优化**:新版将 JSX 运行时分离到独立包,未使用的 JSX 代码可以被正确摇树优化。
82+
83+
**简化开发体验**:不再需要手动引入 React,减少了开发者的心智负担。
84+
85+
**性能优化**:新的 children 传递方式(通过 config.children)为后续的优化提供了更好的基础。
86+
87+
### 2. 虚拟 DOM 创建的精妙设计
88+
89+
在实现 `jsx()` 函数时,发现了几个关键的设计细节:
90+
91+
**安全属性复制**
92+
```typescript
93+
// 只复制自身属性,防止原型链污染
94+
if (hasOwnProperty.call(config, prop)) {
95+
props[prop] = val;
96+
}
97+
```
98+
99+
**Symbol 标识的重要性**
100+
```typescript
101+
$$typeof: REACT_ELEMENT_TYPE // Symbol.for('react.element')
102+
```
103+
这个设计是为了防止 XSS 攻击,确保只有 React 创建的对象才能被识别为合法的 React Element。
104+
105+
### 3. 在 React 整体架构中的位置
106+
107+
通过这次实现,明确了 JSX 转换在 React 架构中的关键作用:
108+
109+
```
110+
JSX 语法
111+
↓ (Babel 编译时)
112+
jsx() 函数调用
113+
↓ (运行时 - react 包)
114+
React Element 对象
115+
↓ (协调阶段 - react-reconciler)
116+
Fiber 节点
117+
↓ (渲染阶段 - react-dom)
118+
真实 DOM
119+
```
120+
121+
**承上启下的桥梁**:JSX 转换是连接开发者编写的声明式代码与 React 内部 imperative 渲染逻辑的关键桥梁。
122+
123+
### 4. 实际开发中的应用价值
124+
125+
**调试能力提升**:通过自定义 `_mark: '_juanlou'` 字段,可以在开发过程中快速识别自定义 React 实现创建的元素。
126+
127+
**理解 Babel 配置**:现在能准确理解为什么项目中需要配置 `@babel/preset-react``runtime` 选项。
128+
129+
**性能优化意识**:明白了为什么 React 团队要改变 children 的传递方式 - 为未来的编译器优化做准备。
130+
131+
这次实践不仅实现了功能,更重要的是通过代码变更理解了 React 团队的设计决策背后的深层原因,为后续学习 Fiber 架构和协调算法打下了坚实的基础。
132+
133+
---
134+
*🤖 由 AI Commit Note 自动生成*

0 commit comments

Comments
 (0)