React 的设计哲学建立在一套清晰的核心思想上,它们共同决定了 React 应用的架构方式、数据流动方式和性能特征。理解这些思想,是写好 React 代码的根本。
1.2.1 组件化:把界面拆成可复用的积木
组件是 React 应用的最小构建单元。一个组件本质上是一个返回 UI 描述的函数(现代函数组件)或者一个具有渲染能力的类(旧式类组件)。它封装了特定的视觉结构和交互逻辑,可以独立开发、独立测试、独立复用。
组件化的实际价值:
- 高内聚:一个组件内部的 HTML 结构、样式和交互逻辑紧密相关,放在一起维护,避免“改一处动全身”。
- 低耦合:组件之间通过明确的接口(Props)通信,内部实现对外部隐藏。
- 可组合:小组件可以像搭积木一样组合成复杂页面,提升开发效率。
示例:将页面拆分成组件树
一个典型的后台界面可以这样拆分:
App
├── Header
│ ├── Logo
│ └── UserMenu
├── Sidebar
│ └── MenuItem
└── MainContent
└── DataTable
└── Pagination
每个组件只关注自己的职责,App 组件负责组合整体布局,DataTable 只需接收数据并渲染,不必知道数据来自哪个 API。这种拆分方式让代码天然具备可维护性和可扩展性。
函数组件的标准写法:
function UserCard({ name, avatar, email }) {
return (
<div className="user-card">
<img src={avatar} alt={name} />
<h3>{name}</h3>
<p>{email}</p>
</div>
);
}
只需关注“输入 Props → 输出 UI”,简洁且可测试。
1.2.2 单向数据流:数据一路向下,行为一路向上
React 中数据的流动遵循单向数据绑定原则:状态(State)总是由某个组件“拥有”,并通过 Props 向下传递给子组件。当子组件需要触发状态变更时,它不能直接修改父组件的状态,而是通过调用父组件通过 Props 传递下来的回调函数,将“意图”向上传递。
状态变更方向:父 → 子(通过 Props)
事件通知方向:子 → 父(通过回调函数)
这种模式让数据变化过程变得非常清晰、可追溯。当 UI 出现问题时,你只需沿着组件树向上查找数据来源,而不必猜测“谁修改了我的数据”。
实际示例:
function Parent() {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return (
<div>
<p>当前计数:{count}</p>
<Child onIncrement={increment} />
</div>
);
}
function Child({ onIncrement }) {
return <button onClick={onIncrement}>增加</button>;
}
count 的“所有权”在 Parent,Child 只是一个“触发器”。任何对 count 的变更都发生在 Parent 内部,这让调试变得极其简单:所有状态变更都集中在一处。
对比双向绑定(如 Vue 的 v-model 本质):
双向绑定虽然写起来方便,但当应用规模变大、数据来源变多时,数据流向容易失控。React 的选择是牺牲一点点便利性,换取更强的可预测性。在实际开发中,你会发现这种约束反而能避免很多隐蔽的 bug。
1.2.3 虚拟 DOM:用 JavaScript 描述界面,最小化真实 DOM 操作
操作真实 DOM 的代价很高——每次修改都可能触发浏览器的重排(Reflow)和重绘(Repaint),频繁操作会直接导致性能问题。React 的解决方案是虚拟 DOM。
虚拟 DOM 的本质:
一个轻量级的 JavaScript 对象,用于描述界面的结构。例如,下面的 JSX:
<div id="app">
<h1>Hello</h1>
</div>
会被编译成类似这样的虚拟 DOM 对象:
{
type: 'div',
props: { id: 'app' },
children: [
{
type: 'h1',
props: null,
children: ['Hello']
}
]
}
工作流程:
- 当应用首次渲染时,React 根据组件树生成一整棵虚拟 DOM 树,然后将其一次性转换为真实 DOM,挂载到页面。
- 当状态发生变化时,React 生成一棵新的虚拟 DOM 树。
- React 通过 Diff 算法比较新旧两棵虚拟 DOM 树,找出需要更新的最小差异集合。
- 最后,只将这些差异批量更新到真实 DOM 上。
虚拟 DOM 的三个核心价值:
- 性能优化:通过批量操作和最小化更新,避免不必要的 DOM 操作。
- 跨平台抽象:虚拟 DOM 不直接依赖浏览器环境,React 可以将同样的虚拟 DOM 渲染到不同平台——Web DOM、React Native 的原生组件、Canvas 甚至终端。这正是“Learn Once, Write Anywhere”的技术基础。
- 开发体验提升:开发者无需手动管理 DOM 更新,只需声明 UI 应该是什么样,React 负责高效实现。
一种常见的误解澄清:
虚拟 DOM 并不总能比精心手写的 DOM 操作更快,特别是在极简单场景下。它的优势在于中等复杂度以上应用中,自动化的 Diff 和批量更新通常能压倒手工优化,同时极大地降低了开发者的心智负担。而且,虚拟 DOM 让跨平台成为可能,这是手工操作 DOM 难以做到的。
1.2.4 三位一体的协作
这三个核心思想并非孤立存在,而是紧密配合的:
- 组件化 提供了 UI 的拆分和组合方式,每个组件内部管理自己的状态。
- 单向数据流 规定了组件间数据传递的方向,使得组件间的协作可预测。
- 虚拟 DOM 让组件在状态更新时能够高效地重渲染,保证了声明式的流畅体验。
它们共同构成 React 的“稳定三角”,无论 React 的 API 如何演进(从类组件到 Hooks,从同步渲染到并发渲染),这些核心理念始终未变。