React 是用于构建用户界面的 JavaScript 库,Angular 是用于构建 Web 应用的完整框架。使用 React 时,你把组件写成返回 JSX 的函数,并为路由、表单和数据分别选择工具;使用 Angular 时,你编写带 HTML 模板的 TypeScript 类,路由、表单、HTTP 客户端和依赖注入都开箱即用。下面是用两者分别实现的同一个计数器。
这个组件的 Angular 版本:
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-counter',
template: `
<button (click)="increment()">Clicked {{ count() }} times</button>
`,
})
export class CounterComponent {
count = signal(0);
increment() {
this.count.update((n) => n + 1);
}
}
两者的概念一一对应:React 的 useState(0) 就是 Angular 的 signal(0),onClick={...} 就是 (click)="...",{count} 就是 {{ count() }}。区别在于代码放在哪里:React 中是一个返回标记的函数,Angular 中是一个类加一段模板字符串。
库与框架
这是决定其他大部分差异的根本区别。React 负责渲染和组件状态,其余一切由你选择:
- 路由:React Router、TanStack Router,或者框架提供的基于文件的路由。
- 数据获取:在 effect 中用
fetch、TanStack Query,或者框架的 loader 和服务器组件。 - 表单:普通的受控输入框、React 19 的表单 action,或者 React Hook Form。
- 全局状态:context、Zustand、Redux Toolkit、Jotai。
很多团队直接从 Next.js 或框架模式下的 React Router 这样的 React 框架起步,省去了大部分选择,因为这些框架已经打包好了路由、数据加载和服务端渲染。
Angular 替你做好了这些选择:@angular/router、响应式表单和模板驱动表单、HttpClient、依赖注入、测试配置,以及可以生成组件和服务的 ng CLI。每个 Angular 项目的结构大体相同,这是大型组织选择它的常见原因。代价是要学的东西更多,替换其中某一部分的自由也更少。
JSX 与模板
React 组件返回 JSX,而 JSX 就是 JavaScript。条件用 && 或三元运算符,列表用 .map(),JavaScript 能做的事在标记中都能做。Angular 模板是带有自己语法的 HTML:@if、带 track 的 @for、[property] 绑定、(event) 绑定以及 {{ }} 插值。模板让标记和逻辑明显分开;JSX 把它们放在一起,并让你使用完整的语言。下面是一个过滤列表,这是要对比的第二个功能。
在输入框中输入 an 并观察控制台:每次按键整个函数都会重新运行,visible 只是被重新计算了一遍。同一个组件在 Angular 中的写法,模板放在单独的文件中:
import { Component, computed, signal } from '@angular/core';
@Component({
selector: 'app-fruit-filter',
templateUrl: './fruit-filter.component.html',
})
export class FruitFilterComponent {
fruits = ['Apple', 'Banana', 'Cherry', 'Grape', 'Mango', 'Peach'];
query = signal('');
visible = computed(() =>
this.fruits.filter((f) => f.toLowerCase().includes(this.query().toLowerCase()))
);
}
<input #box [value]="query()" (input)="query.set(box.value)" placeholder="Filter fruit" />
<ul>
@for (fruit of visible(); track fruit) {
<li>{{ fruit }}</li>
} @empty {
<li>No match</li>
}
</ul>
在 Angular 中,computed 声明了 visible 依赖于 query,所以 Angular 知道哪个模板读取了它,并且只在 query 变化时重新计算 visible。React 中没有这种声明:组件重新运行,值也就重新计算。React 中的 key={fruit} 和 Angular 中的 track fruit 作用相同,都是告诉框架列表中的哪一项对应哪一项。
JavaScript 优先与 TypeScript 优先
React 是带 JSX 的纯 JavaScript,TypeScript 是你可以选择加上的(npm create vite@latest my-app -- --template react-ts)。大多数新的 React 项目都会加上它,但你不懂类型也能学 React。Angular 是为 TypeScript 构建的:装饰器、依赖注入和模板类型检查器都以它为前提。如果你的团队已经在写带类型的代码,这就不是问题;如果你刚开始学编程,这就意味着要同时多学一样东西。React 与 TypeScript 页面展示了 React 这边如何使用类型。
数据流与变更检测
两者都通过输入向下传递数据(React 中是 props,Angular 中是 input() 或 @Input()),并通过回调向上发送事件(React 中是作为 props 传入的函数,Angular 中是 output() 或 @Output())。区别在于各自如何察觉变化。
React 把 state 看作不可变的快照。你用新值调用 setter,React 重新运行组件函数,把新的 JSX 与旧的比较,然后修补 DOM。没有任何东西被自动追踪:渲染函数本身就是依赖关系图。这样很容易推理,代价是有时需要加上 memo、useMemo 或 useCallback(或者让 React Compiler 替你加)来跳过不必要的工作。
Angular 过去用 Zone.js 检测所有异步事件,然后在组件树中检查有变化的绑定。现代 Angular 正在转向 signals:signal、computed 和 effect 追踪每个模板读取了哪些值,所以 Angular 只检查 signal 发生变化的组件,最近的版本甚至可以完全不用 Zone.js。Angular 模板不会像 React 组件那样在每次变化时重新运行整个函数。
在日常代码中,两者的感受比底层机制所显示的更接近:你持有 state,从中派生出值,页面随之更新。
状态管理
在 React 中,局部状态用 useState 或 useReducer,共享状态提升到父组件或放进 context,全局状态通常放在一个小型的状态管理库中。在 Angular 中,局部状态是组件上的 signals,共享状态通常放在一个 service 中,并在需要的地方注入;依赖注入就是 Angular 对“两个相距很远的组件如何共享数据”给出的内置答案。想要 Redux 风格 store 的团队可以用 NgRx。React 没有依赖注入系统,context 起着类似的作用。
对比表
| React | Angular | |
|---|---|---|
| 定位 | UI 库 | 完整的应用框架 |
| 语言 | JavaScript 或 TypeScript | TypeScript |
| 标记 | JavaScript 中的 JSX | 使用 Angular 语法的 HTML 模板 |
| 组件形式 | 返回 JSX 的函数 | 带装饰器和模板的类 |
| 局部状态 | useState、useReducer | Signals(signal、computed) |
| 更新方式 | 组件重新运行,React 比较输出差异 | signals 和变更检测更新绑定 |
| 共享状态 | props、context、状态管理库 | 注入的 service、signals、NgRx |
| 路由 | 独立的库或框架 | 内置(@angular/router) |
| 表单 | 自由选择,另有 React 19 表单 action | 内置(响应式表单和模板表单) |
| HTTP | fetch 或第三方库 | 内置(HttpClient) |
| 依赖注入 | 无(最接近的是 context) | 内置 |
| 工具 | Vite 或框架的 CLI | Angular CLI(ng) |
| 服务端渲染 | Next.js、React Router 框架模式 | Angular SSR |
| 移动应用 | React Native | Ionic 搭配 Capacitor、NativeScript |
| 维护者 | Meta 和社区 |
学习曲线
React 上手更快。会 JavaScript 的初学者学完组件、props、state 和 effect 就能做出真正的东西,React 是什么页面几分钟就能讲清整体思路。学习的负担被推到了后面:你得选择路由、数据获取方式和表单方案,而不同的 React 代码库做出的选择各不相同。
Angular 的起步更陡:TypeScript、装饰器、模板、signals、依赖注入、路由和表单模块,以及部分 API 用到的 RxJS。不过一旦掌握,每个 Angular 项目都以同样的方式使用同样的组件,在项目之间切换也更容易。
该选哪个
选择 React,如果:
- 你想要一个小巧的核心,其余部分自由选择;或者想用 Next.js 这样的框架来做服务端渲染和基于文件的路由。
- 你还打算开发移动应用,React Native 沿用同样的组件模型。
- 团队大多熟悉 JavaScript,或者你正在学前端开发,想用最短的路径做出能用的应用。
选择 Angular,如果:
- 大型团队需要在许多项目中使用统一的标准结构,减少架构决策上的争论。
- 你希望表单、HTTP、路由和依赖注入由同一个团队一起维护,并通过 CLI 一起升级。
- 团队已经在写 TypeScript,喜欢基于类的 service,以及模板与逻辑之间的清晰分离。
两者都很成熟,在生产环境中被广泛使用,对职业发展都有帮助。技能也是相通的:组件、单向数据流、派生状态和响应式更新,在两者中都是同样的概念。
常见问题
React 和 Angular 哪个更好?
总体上没有哪个更好。Angular 提供一套完整、有明确约定的工具,适合希望每个项目结构都一致的大型团队。React 提供一个小巧的核心,其余部分自由选择,适合追求灵活性或想使用 Next.js 等框架的团队。
React 比 Angular 更容易学吗?
通常是的,至少在入门阶段。React 的核心是组件、props、state 和几个 hook,全部用 JavaScript 编写。Angular 要求你先学 TypeScript、装饰器、模板、依赖注入、signals,以及它为表单和 HTTP 选定的模块,然后才能做出像样的东西。不过之后 Angular 需要你做的决定更少。
Angular 是框架,React 是库吗?
是的。Angular 把路由、表单、HTTP 客户端、依赖注入、测试配置和 CLI 作为一个框架一起提供。React 只负责渲染 UI;路由、数据获取和表单来自独立的库,或者来自 Next.js、React Router 这样的 React 框架。
Angular 用 TypeScript,React 用 JavaScript 吗?
Angular 是为 TypeScript 设计的,它的工具链默认你在用 TypeScript。React 使用纯 JavaScript 和 TypeScript 都同样好用;大多数新的 React 项目会选择 TypeScript,但这不是必须的。
可以从 Angular 转到 React 吗?
可以,概念都是相通的:组件、输入(props)、输出(回调 props)和响应式 state。主要的调整是用 JSX 代替模板、用 hooks 代替类成员,以及自己选择路由和表单库。