React
是一个前端的 UI 框架,背后的源代码实际上比较复杂,但其背后的设计理念值得我们学习。
组件化
React 强调将用户界面分解成可复用的组件。这些组件可以嵌套和组合,以构建复杂的用户界面。每个组件拥有自己的状态和生命周期,有助于提高代码的可维护性和可重用性。
声明式编程
React 同时倡导函数式编程和声明式编程,但二者在 React 中的角色和体现方式有所不同。以下是详细解释:
声明式编程是 React 的核心设计理念。
-
特点:开发者描述 UI 应该是什么样子,而不是一步步告诉计算机如何实现, React 复杂将声明式的 UI 抽象转化为具体的 DOM 操作。
-
具体体现:
- 组件开发:通过 JSX 声明组件的结构和逻辑(如
<Button onClick={handleClick}>Submit</Button>
),无需手动操作 DOM。 - 状态驱动视图:当状态(
state
)变化时,React 自动重新渲染并高效更新 UI(开发者无需手动操作 DOM)。 - 虚拟 DOM:React 通过对比虚拟 DOM 的差异,自动计算最小化 DOM 操作,隐藏了底层的命令式细节。
- 组件开发:通过 JSX 声明组件的结构和逻辑(如
import { useState } from "react";
const App = () => {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}
总结: React 的声明式特性让开发者专注于逻辑和结果,而并非底层实现。
函数式编程
函数式编程是 React 实现声明式 UI 的重要工具。
-
特点:强调纯函数、不可变数据和副作用管理,通过组合函数构建逻辑。
-
React 中的体现
- 函数组件:React 推荐通过纯函数来渲染 UI
- Hooks:通过 useState, useEffect 等 hook 来管理状态和副作用,鼓励不可变数据更新。
- 高阶组件:通过函数组合复用逻辑(如
withRouter(Component)
)。 - 不可变性:状态更新时创建新对象/数组(如
[...list, newItem]
),避免直接修改原数据。
总结:函数式编程帮助 React 实现可预测、可维护的声明式代码。
虚拟 DOM
核心:通过内存中轻量的 DOM 表示和 Diff 算法,高效更新真实 DOM
意义:最小化渲染成本,提升性能,实现跨平台渲染(如 React Native)。
单向数据流
**核心:**React 中,数据是单向流动的,数据只能从父组件流向子组件。这这模式使用数据管理更为清晰,方便预测应用状态的变化。
意义:数据流动清晰,降低副作用,易于调试和维护。
组合优于继承(Composition over Inheritance)
- 核心:通过组件组合(如
props.children
、Hooks)复用逻辑,而非类继承。 - 意义:灵活解耦,避免传统继承的层级复杂性。
不可变性(Immutability)
- 核心:状态更新通过创建新对象/数组(而非直接修改原数据),例如使用
setState
或不可变库(如 Immer)。 - 意义:确保状态变化的可追踪性,简化渲染优化(如浅比较),支持时间旅行调试(如 Redux DevTools)。
副作用处理
实际上 React
不是完全的函数式编程,因为实际上一个 web 页面,也需要处理很多的副作用,如请求,监听事件,手动 DOM 操作等能力。
这个时候我们单靠函数式编程是搞不定的,所以 react 提供了一些内部机制,如 hook 等让我们来处理副作用,从而保持一定的灵活性。
具体如 useEffect
去进行请求。
const App = () => {
useEffect(() => {
fetch();
}, [])
};
总结
React 的核心设计哲学可归结为:用组件化的声明式语法描述 UI,通过虚拟 DOM 和单向数据流高效更新视图,优先通过组合而非继承实现复用,并依赖不可变性保障状态的可控性。这些原则共同构建了 React 的高效性、灵活性和可维护性。