Menu

React 和 Angular 的区别:怎么选

React 是需要和其他工具搭配使用的 UI 库;Angular 是内置路由、表单、HTTP 和依赖注入的完整框架。并排对比用两者写出的同一个组件。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

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 起着类似的作用。

对比表

ReactAngular
定位UI 库完整的应用框架
语言JavaScript 或 TypeScriptTypeScript
标记JavaScript 中的 JSX使用 Angular 语法的 HTML 模板
组件形式返回 JSX 的函数带装饰器和模板的类
局部状态useState、useReducerSignals(signal、computed)
更新方式组件重新运行,React 比较输出差异signals 和变更检测更新绑定
共享状态props、context、状态管理库注入的 service、signals、NgRx
路由独立的库或框架内置(@angular/router)
表单自由选择,另有 React 19 表单 action内置(响应式表单和模板表单)
HTTPfetch 或第三方库内置(HttpClient)
依赖注入无(最接近的是 context)内置
工具Vite 或框架的 CLIAngular CLI(ng)
服务端渲染Next.js、React Router 框架模式Angular SSR
移动应用React NativeIonic 搭配 Capacitor、NativeScript
维护者Meta 和社区Google

学习曲线

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 代替类成员,以及自己选择路由和表单库。

Coddy 编程语言插图

和 Coddy 一起学编程

开始