Angular7 入门总结 从环境搭建到路由的完整笔记
起因是我要做一个 Ionic 4 的混合应用。Ionic 那几个大版本一直绑着 Angular,模板语法、依赖注入、模块声明全是 Angular 那一套,不把 Angular 和 TypeScript 的基础补上,连一个页面跳转都写不明白。我之前整理过一篇 Ionic 3 的踩坑总结,当时是硬着头皮往前推的,这次干脆停下来,把 Angular 7 从头过一遍,边写 demo 边记,攒成了这篇笔记。
所以这篇不打算论证「Angular 有多好」。它更像是一个从 jQuery、Vue 那边过来的人,把 Angular 的心智模型对齐到能上手写业务的程度。读完你应该能独立搭起项目、写组件、拆服务、配路由,也能看懂别人的 Angular 代码在干什么。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
- Angular 的定位,以及它和 Vue、React 在工程取向上的差别
- 用 Angular CLI 搭环境、建项目,生成的目录里哪几个文件才是重点
- 组件、模板语法、内置指令、管道,配三个能跑起来的完整小案例
- 服务与依赖注入,怎么把状态从组件里挪出去
- 八个生命周期钩子的触发顺序,以及每一个该干什么
- RxJS 的 Observable 和 Promise 到底差在哪,RxJS 6 又改了什么
- 用 HttpClient 发 get、post、jsonp 请求
- 路由配置、路由传参、js 跳转和父子路由
# 一、Angular 介绍
Angular 是谷歌开源的 web 前端框架,前身 AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后来被 Google 接手维护,Google 自家不少产品都在用它。
它和 Vue、React 最大的差别不在语法,而在「给不给你选择」这件事上。Vue 和 React 都是库或者说轻框架,路由、状态、HTTP 请求你自己配;Angular 是把路由、依赖注入、HTTP 客户端、表单、测试脚手架一整套全给你,代价是你得接受它的写法。这套取向在中大型企业级项目里很省心,几十个人的团队目录结构和分层方式天然一致;放到三五个页面的小项目上,就显得笨重。
- 从 2019 年初的项目数统计看,
angular(1.x、2.x、4.x、5.x、6.x、7.x)加起来的存量非常大,尤其是企业内部系统 Angular从 2.x 开始就以TypeScript为一等公民,类型、装饰器、接口这些都是日常写法,不是可选项
写这篇的时候是 2018 年 11 月发布的 angular7.x。官方走的是固定节奏的大版本发布,每隔几个月就会有一个新的主版本号,所以这份笔记里的基础概念同样适用于后面的 Angular8.x、Angular9.x。

这里得先说一句时效性。这篇写于 Angular 7 时代,之后 Angular 的大版本已经走出去很远了。Ivy 渲染器、standalone components(不用再写 NgModule 的独立组件)、signals 这套细粒度响应式,还有 @if / @for 这类新的模板控制流语法,都是这篇之后才有的东西。本文的写法在当年的项目里是标准写法,现在读到的老代码大量还是这个样子,所以留着不动是有价值的;但如果你是新起项目,具体用哪套 API 请以官方文档当前版本为准,我不确定各个特性具体落在哪个版本号上,就不在这里乱猜了。后面每一章我都会在末尾单独起一小段,说清楚这块后来往哪个方向演进了。
学习 Angular 必备基础
想顺畅读下去,html、css、js、es6 这几样是底子,另外 TypeScript 得会一点。倒不用把泛型、条件类型这些啃透,能看懂类型注解、interface、class 和装饰器语法就够开工了,剩下的边写边补。
# 二、Angular 环境搭建及创建项目
# 2.1 环境搭建
Angular 的工程化程度高,好处是脚手架帮你把编译、开发服务器、测试、打包全配好了,坏处是环境这一步没弄对,后面全是莫名其妙的报错。所以这一节值得慢一点。
1. 安装 nodejs
装 angular 的机器上必须有 nodejs,选 LTS 稳定版,别去追奇数版本号的当前版。Angular CLI 每个大版本都有自己支持的 Node 版本区间,装之前先去官方的版本兼容表对一眼,能省掉一大半「安装成功但 ng serve 起不来」的问题。
2. 安装 cnpm
当年国内直连 npm 官方源经常超时,@angular/cli 这个包依赖又特别多,所以一般先用 npm 装一个走淘宝镜像的 cnpm。
npm install -g cnpm --registry=https://registry.npm.taobao.org
这里有个坑要注意,淘宝源后来做过域名迁移,registry.npm.taobao.org 这个地址已经不是主推的了,现在的地址是 registry.npmmirror.com。你要是照上面这行敲报证书错误,八成就是撞上这个了,换成新域名即可。另外现在 npm 本身速度也还行,直接 npm config set registry 换源比再装一层 cnpm 更干净,cnpm 扁平化 node_modules 的方式偶尔会和某些包的路径假设打架。
3. 使用 npm/cnpm 命令安装 angular/cli
@angular/cli 是全局命令行工具,装完你就有了 ng 这个命令,后面建项目、生成组件、起开发服务器全靠它。
npm install -g @angular/cli
# 或者
cnpm install -g @angular/cli
装完敲 ng v,它会打印 CLI 版本、Angular 各个包的版本、Node 版本和操作系统。这一步不只是确认装没装上,更重要的是核对 CLI 版本和你要建的项目版本是不是一套。

4. 安装插件
编辑器插件不是必需品,但差别很大。Angular 的模板是单独的 .html 文件,里面写的 *ngFor、[ngClass] 这些默认是没有提示的,装上语言服务插件之后,模板里能直接跳转到组件的属性定义,写错属性名当场标红。

5. 安装chrome扩展
augury 是当年调 Angular 的浏览器扩展,地址是 https://augury.angular.io/ ,它能把当前页面的组件树画出来,点开某个组件可以看到它的输入属性、注入了哪些服务、变更检测的状态。排查「数据明明改了视图没动」这类问题的时候,比一路 console.log 快得多。

补一句时效性。augury 是针对 Ivy 之前的渲染器写的,Angular 切到 Ivy 之后它就不再适用了,官方后来另出了 Angular DevTools 扩展接替这个位置,功能上也是组件树加变更检测分析。具体从哪个版本开始换,以官方文档为准。
# 2.2 创建项目
环境好了就可以起项目了。ng new 会问你要不要路由、样式用 CSS 还是 SCSS,按需要选就行,选完它会自动跑一次依赖安装。
# 创建项目
ng new my-app
cd my-app
# 运行项目
ng serve --open
ng serve 起的是带热更新的开发服务器,默认端口 4200,--open 会顺手帮你把浏览器打开。这一步如果卡在依赖安装上,可以加 --skip-install 先把目录结构生成出来,再手动装依赖,后面第十章建路由项目的时候就是这么干的。
# 2.3 目录结构分析
ng new 一口气生成了几十个文件,第一次看会有点懵。其实真正日常会动的就那么几个,剩下的是配置和测试脚手架,知道它们存在就行。

完整的文件说明可以参考官方的 https://www.angular.cn/guide/file-structure ,这里只挑重点讲。
app目录(重点)
app 目录是我们真正写代码的地方,业务代码全在这儿。一个 Angular 程序至少需要一个模块和一个组件,新建项目的时候 CLI 已经默认帮你生成好了,这也是 Angular 和 Vue 那种「一个 main.js 挂上去就行」最直观的区别,它一开始就强制你分模块。

先看 app.component.ts,这个文件表示一个组件。组件是 Angular 应用的基本构建单元,你可以把它理解成一段带着业务逻辑和数据的 Html。下面这张图是它的默认内容,我们逐行拆一下每部分在干什么。

/*这里是从Angular核心模块里面引入了component装饰器*/
import {Component} from '@angular/core';
/*用装饰器定义了一个组件以及组件的元数据 所有的组件都必须使用这个装饰器来注解*/
@Component({
/*组件元数据 Angular会通过这里面的属性来渲染组件并执行逻辑
* selector就是css选择器,表示这个组件可以通过app-root来调用,index.html中有个<app-root>Loading...</app-root>标签,这个标签用来展示该组件的内容
*templateUrl 组件的模板,定义了组件的布局和内容
*styleUrls 该模板引用那个css样式
* */
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
/*AppComponent本来就是一个普通的typescript类,但是上面的组件元数据装饰器告诉Angular,AppComponent是一个组件,需要把一些元数据附加到这个类上,Angular就会把AppComponent当组件来处理*/
export class AppComponent {
/*这个类实际上就是该组件的控制器,我们的业务逻辑就是在这个类中编写*/
title = '学习Angular';
}
组件相关的概念
上面这段代码信息量不小,把它拆成三块看就清楚了。
第一块是组件元数据装饰器 @Component,简称组件装饰器,作用是告诉 Angular 框架该怎么处理一个普通的 TypeScript 类。它里面写的那些属性叫元数据,Angular 会读这些元数据来渲染组件、执行组件逻辑。selector 决定这个组件在别的模板里用什么标签调用,templateUrl 指向布局文件,styleUrls 指向样式文件。
第二块是模板 Template,也就是组件的外观。模板以 html 形式存在,长得很像普通 HTML,但可以用 Angular 的数据绑定语法把控制器里的数据渲染出来。
第三块是控制器 controller,就是被 @Component 装饰的那个普通 TypeScript 类。组件所有的属性和方法都挂在这里,绝大多数业务逻辑也写在这里。模板和控制器之间靠数据绑定通信,模板展示控制器的数据,控制器处理模板上冒出来的事件。
装饰器、模板、控制器是组件的必备要素。除此之外还有一些可选项,用到的时候再回来查:
- 输入属性
@Input,用来接收外部传进来的数据。Angular的程序结构本身就是一棵组件树,输入属性让数据能在这棵树上往下传 - 提供器
providers,做依赖注入用的,第四章会展开 - 生命周期钩子
LifeCycle Hooks,一个组件从创建到销毁会依次触发一串钩子,和 Android 里Activity的生命周期是同一个套路,第七章专门讲 - 样式表,组件可以关联自己的样式,而且默认是有作用域隔离的
- 动画
Animations,Angular提供了独立的动画包,做淡入淡出这类跟组件状态挂钩的效果比手写 CSS class 切换清楚 - 输出属性
@Output,用来往外抛事件,或者在组件之间共享数据