1.1 Angular框架概述与变更检测初遇


文档摘要

1.1 Angular 框架概述与变更检测初遇 Angular 是 Google 主导的全功能前端框架,覆盖模板、依赖注入、路由、表单、HTTP、测试与服务端渲染。本节先讲清楚它在框架谱系中的定位与哲学,再通过一个最小实验让读者第一次"看见"变更检测——框架发现数据变化并更新屏幕的机制,这也是贯穿整本教程的主线。 学习目标 读完本节你应当能够: 复述 Angular 从 AngularJS 到现代版本的演进脉络,说出重写的原因。 对比 Angular 与 React、Vue 在"框架边界"上的差异,判断三者各自的适用场景。 跑通一个计数器实验,观察点击事件后界面如何自动更新,并用"变更检测"解释它。 说出变更检测两个基本问题的初步答案:何时检查、检查什么。

1.1 Angular 框架概述与变更检测初遇

Angular 是 Google 主导的全功能前端框架,覆盖模板、依赖注入、路由、表单、HTTP、测试与服务端渲染。本节先讲清楚它在框架谱系中的定位与哲学,再通过一个最小实验让读者第一次"看见"变更检测——框架发现数据变化并更新屏幕的机制,这也是贯穿整本教程的主线。

学习目标

读完本节你应当能够:

  1. 复述 Angular 从 AngularJS 到现代版本的演进脉络,说出重写的原因。
  2. 对比 Angular 与 React、Vue 在"框架边界"上的差异,判断三者各自的适用场景。
  3. 跑通一个计数器实验,观察点击事件后界面如何自动更新,并用"变更检测"解释它。
  4. 说出变更检测两个基本问题的初步答案:何时检查、检查什么。

一、从一段历史说起

2010 年 AngularJS 发布时,前端还处于 jQuery 统治的年代。它的杀手锏是双向绑定:改了模型,视图自动跟着变,这在当时近乎魔法。实现这套魔法的核心就是脏检查——在每次浏览器事件后,把所有被监视的表达式重新算一遍,跟旧值比对,不同就更新 DOM。

但 AngularJS 的脏检查作用在作用域上,嵌套作用域加上双向数据流,让大型应用的更新路径变得不可预测。2014 年至 2016 年,Google 做了一次彻底重写,也就是现在的 Angular:组件树取代作用域树,数据流默认单向,脏检查升级为树形的变更检测。理解这段历史很重要——Angular 的很多设计不是凭空发明的,而是对上一代痛点的直接回应。

AngularJS 时代的同款计数器长这样——注意检查的单位是"作用域"而不是组件:

<!-- AngularJS:把表达式挂到作用域上,由框架逐轮"盯着"重算 --> <div ng-controller="CounterCtrl as vm"> <p>当前计数:{{ vm.count }}</p> <button ng-click="vm.increment()">加一</button> </div>
// AngularJS 控制器:数据与监听都注册在作用域上,双向绑定靠脏检查轮询兜底 app.controller('CounterCtrl', function () { this.count = 0; // 挂到作用域的数据才会被监视 this.increment = () => { this.count += 1; // 改完作用域,等下一轮 digest 重算插值 }; });

我常跟团队讲的判断是:React 是"库 + 自由拼装",Vue 是"渐进式框架",Angular 则是"全家桶 + 强约定"。三者没有绝对优劣,但一旦应用规模大到几十人协作、生命周期以十年计,强约定的价值就会指数级上升——所有人写出的代码长得差不多,换人接手成本极低。

二、框架哲学对比

维度 Angular React Vue
定位 全功能框架 视图层库 渐进式框架
模板 HTML 增强语法 JSX 模板 + 可选 JSX
依赖注入 内置 Injector 树 无,靠闭包与参数传递 无,靠 provide/inject
变更检测 框架内建,默认全树检查 setState 后该组件子树重渲染 响应式代理,精确到属性
工程约束 CLI 强约定,风格统一 自由组合,约定靠社区 介于两者之间

注意表中"变更检测"一行:React 的更新由开发者显式触发,Vue 靠数据代理自动追踪,Angular 则默认在异步事件后对组件树做检查。这个差异会一路影响后续章节里 OnPush、管道纯度、trackBy 等所有话题。

💡 一个直觉:React 把"何时更新"交给你,Vue 把"哪个数据变了"交给代理,Angular 把"更新"整体承包——你只需要声明界面长什么样,剩下的它兜底。

三、第一次看见变更检测

不用急着装环境,先看代码。下面是一个最小的 Angular 组件(现代 standalone 写法),一个按钮加一个计数显示:

import { Component, signal } from '@angular/core'; // 组件 = 模板 + 类 + 样式,Angular 应用的基本构件 @Component({ selector: 'app-counter', // 自定义标签名 template: ` <p>当前计数:{{ count() }}</p> <!-- 插值绑定,变更检测的采样点 --> <button (click)="increment()">加一</button> <!-- 事件绑定,异步事件的入口 --> ` }) export class CounterComponent { count = signal(0); // 信号:Angular 新一代响应式原语 increment() { this.count.set(this.count() + 1); // 只改数据,没有任何操作 DOM 的代码 } }

按下按钮后屏幕上的数字变了,但类里找不到一行 document.querySelector 之类的 DOM 操作。是谁更新了界面?答案分三步:

  1. Zone.js 拦截了浏览器的 click 事件(这是 Angular 在启动时打的补丁);
  2. 事件回调执行完毕后,Zone.js 通知 Angular:"一次异步事件结束了";
  3. Angular 从根组件开始对整棵组件树做变更检测——重新计算每个绑定表达式,发现 count() 的返回值从 0 变成了 1,于是更新对应的 DOM 文本节点。

图:一次点击背后的完整旅程

图:一次点击背后的完整旅程

⚠️ 常见误解:以为 {{ count() }} 里的函数调用是 Angular 在"轮询"。实际上它只在变更检测运行时被求值,没有变化就跳过 DOM 写入,这就是本册后续讨论性能的起点。

本节要点回顾

  • 演进脉络:现代 Angular 是对 AngularJS 的一次彻底重写,动机是把脏检查从作用域树搬到组件树、把双向流改为单向。
  • 哲学差异:Angular 全家桶 + 强约定,适合长周期大型团队;React 灵活,Vue 渐进,选型看团队与规模。
  • 变更检测的初定义:异步事件结束后,框架从根开始重算绑定表达式、按差异更新 DOM 的机制。
  • 两个基本问题:何时检查(Zone.js 通知,第 3 章展开)、检查什么(组件模板里的绑定,第 2 章展开)。
  • 主线预告:本册把组件、服务、管道、路由都放到变更检测的视角下重新讲一遍。

下一节先把开发环境装好,亲手跑起这个计数器。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U