第1篇 准备 2
第1章 Angular概述 2
1.1 Angular产生的背景 2
1.1.1 Angular与jQuery的不同 2
1.1.2 Angular与React、 Vue.js优势对比 3
1.1.3 Angular、 React、 Vue.js三者怎么选 5
1.2 学习Angular需要什么基础 5
1.2.1 具备面向对象思维 5
1.2.2 熟悉常用的前端开发工具 5
1.2.3 具有一定的前端开发经验 6
1.3 如何使用本书 6
1.3.1 零基础的读者 6
1.3.2 有后端开发经验的读者 7
1.3.3 有前端开发经验的读者 7
1.3.4 有Angular开发经验的读者 7
第2章 实例1:快速创建第一个Angular应用 8
2.1 开发环境准备 8
2.1.1 安装Node js和npm 8
2.1.2 设置npm镜像 9
2.1.3 选择合适的IDE 10
2.1.4 安装Angular CLI 10
2.2 创建第一个应用——hello-world 11
2.2.1 使用Angular CLI初始化应用 11
2.2.2 运行Angular应用 12
2.3 探索Angular 13
2.3.1 src文件夹 13
2.3.2 根目录 14
2.3.3 npm包 16
2.4 配置TypeScript库 18
第2篇 入门 21
第3章 TypeScript基础 21
3.1 了解TypeScript 21
3.1.1 TypeScript与JavaScript、 ECMAScript的关系 21
3.1.2 TypeScript与Angular的关系 22
3.1.3 使用TypeScript的优势 22
3.1.4 TypeScript代码的编译及运行 22
3.2 变量与常量 23
3.2.1 var、 let、 const三者的作用域 23
3.2.2 变量与常量的区别 23
3.2.3 什么是变量提升 24
3.3 TypeScript的数据类型 25
3.3.1 基本类型 25
3.3.2 对象类型 30
3.3.3 任意类型 30
3.3.4 实例2:演示任意类型的使用 31
3.3.5 联合类型 32
3.3.6 交集类型 32
3.4 强大的面向对象体系 33
3.4.1 类 33
3.4.2 接口 37
3.4.3 实例3:演示接口的使用 37
3.4.4 泛型 38
3.4.5 实例4:演示泛型的使用 38
3.4.6 枚举 39
3.5 TypeScript的命名空间 40
3.5.1 声明命名空间 40
3.5.2 实例5:声明命名空间 41
3.5.3 命名空间体 41
3.5.4 导入别名声明 42
3.5.5 实例6:导入别名声明 42
3.5.6 导出声明 43
3.5.7 合并声明 43
3.5.8 实例7:合并声明 43
3.6 TypeScript的模块 44
3.6.1 了解模块 44
3.6.2 实例8:导入声明 45
3.6.3 实例9:导入Require声明 45
3.6.4 实例10:导出声明 46
3.6.5 实例11:导出分配 46
3.6.6 了解CommonJS模块 46
3.6.7 了解AMD模式 47
3.7 装饰器 48
3.7.1 定义装饰器 49
3.7.2 了解装饰器的执行时机 49
3.7.3 认识4类装饰器 51
第4章 实例12:创建一个“用户管理”应用 55
4.1 创建应用 55
4.1.1 新建“用户管理”应用 56
4.1.2 了解Angular组件 56
4.2 修改AppComponent组件 56
4.2.1 修改app.component.ts文件 57
4.2.2 修改app.component.html文件 57
4.2.3 添加应用级别的样式 57
4.3 实现用户编辑器 58
4.3.1 创建用户列表组件 58
4.3.2 添加user属性 60
4.3.3 显示用户 60
4.3.4 显示UsersComponent视图 60
4.3.5 创建User类 61
4.3.6 编辑用户信息 62
4.3.7 添加FormsModule模块 63
4.3.8 声明组件 65
4.4 展示用户列表 65
4.4.1 添加用户列表数据 65
4.4.2 显示用户列表 66
4.4.3 用*ngFor列出用户 66
4.4.4 添加样式 67
4.4.5 添加事件 68
4.4.6 设置选中的样式 70
4.5 多组件化开发 71
4.5.1 创建UserDetailComponent组件 72
4.5.2 编辑user-detail.component.html文件 72
4.5.3 编辑user-detail.component.ts文件 73
4.5.4 编辑users.component.html文件 73
4.6 使用服务 74
4.6.1 服务的好处 74
4.6.2 创建UserService服务 75
4.6.3 提供UserService服务 76
4.6.4 修改UsersComponent组件 77
4.6.5 使用Observable数据 78
4.6.6 显示消息 79
4.7 使用路由 83
4.7.1 路由的用处 83
4.7.2 创建AppRoutingModule 84
4.7.3 添加路由出口 86
4.7.4 添加路由链接 87
4.7.5 添加仪表盘视图 89
4.7.6 导航用户详情 93
4.7.7 支持路由的UserDetailComponent组件 97
4.8 使用HTTP 100
4.8.1 启用HTTP服务 101
4.8.2 模拟数据服务器 102
4.8.3 通过HTTP获取用户数据 105
4.8.4 修改、添加、删除、搜索用户 108
4.9 “用户管理”应用技术点总结 119
4.9.1 Angular架构概览 119
4.9.2 模块 120
4.9.3 组件 121
4.9.4 模板、指令和数据绑定 121
4.9.5 服务与依赖注入 121
4.9.6 路由 122
第3篇 进阶 124
第5章 组件 124
5.1 数据展示 124
5.1.1 实例13:数据展示的例子 124
5.1.2 使用插值表达式显示组件属性 126
5.1.3 组件关联模板的两种方式 126
5.1.4 在模板中使用指令 127
5.2 生命周期 127
5.2.1 生命周期钩子 127
5.2.2 实例14:生命周期钩子的例子 127
5.2.3 生命周期钩子的调用顺序 129
5.2.4 了解OnInit钩子 130
5.2.5 了解OnDestroy钩子 131
5.2.6 了解OnChanges钩子 132
5.2.7 了解DoCheck钩子 132
5.2.8 了解AfterView钩子 133
5.2.9 了解AfterContent钩子 133
5.3 组件交互方式 133
5.3.1 实例15:通过@Input把数据从父组件传到子组件 133
5.3.2 实例16:通过setter监听输入属性值的变化 135
5.3.3 实例17:通过ngOnChanges()方法监听输入属性值的变化 136
5.3.4 实例18:父组件监听子组件的事件 138
5.3.5 实例19:父组件与子组件通过本地变量交互 140
5.3.6 实例20:父组件调用@ViewChild()方法获取子组件的值 141
5.3.7 实例21:父组件和子组件通过服务来通信 143
5.4 样式 146
5.4.1 实例22:使用组件样式的例子 146
5.4.2 样式的作用域 147
5.4.3 特殊的样式选择器 148
5.4.4 把样式加载进组件中的几种方式 149
5.4.5 控制视图的封装模式 150
5.4.6 了解Emulated封装模式 151
5.5 动态加载组件 152
5.5.1 实例23:动态加载组件的例子 152
5.5.2 使用指令 157
5.5.3 加载及解析组件 158
5.5.4 运行效果 159
5.6 自定义元素 160
5.6.1 使用自定义元素 160
5.6.2 自定义元素的工作原理 162
5.6.3 把组件转换成自定义元素 162
5.6.4 实例24:使用自定义元素的例子 163
第6章 模板 168
6.1 模板概述 168
6.1.1 模板的语法 168
6.1.2 模板中的HTML 168
6.2 模板表达式 169
6.2.1 模板表达式上下文 169
6.2.2 编写模板表达式的最佳实践 170
6.2.3 管道操作符 170
6.2.4 安全导航操作符和空属性路径 171
6.2.5 非空断言操作符 171
6.3 模板语句 171
6.3.1 模板语句上下文 172
6.3.2 编写模板语句的最佳实践 172
6.4 数据绑定 173
6.4.1 从数据源到视图 173
6.4.2 从视图到数据源 173
6.4.3 双向绑定 173
6.5 属性绑定 174
6.5.1 单向输入 174
6.5.2 绑定目标 174
6.5.3 一次性字符串初始化 174
6.5.4 选择“插值表达式”还是“属性绑定” 174
6.6 attribute、 class和style绑定 175
6.6.1 attribute绑定 175
6.6.2 class绑定 175
6.6.3 style绑定 176
6.7 事件绑定 176
6.7.1 目标事件 176
6.7.2 $event和事件处理语句 177
6.7.3 使用EventEmitter类自定义事件 177
6.8 模板引用变量 178
6.9 输入和输出属性 179
第7章 指令 180
7.1 指令类型 180
7.2 属性型指令 180
7.2.1 了解NgClass、 NgStyle、 NgModel指令 180
7.2.2 实例25:创建并使用属性型指令 181
7.2.3 实例26:响应用户引发的事件 183
7.2.4 实例27:使用@Input数据绑定向指令传递值 184
7.2.5 实例28:绑定多个属性 186
7.3 结构型指令 187
7.3.1 了解NgIf指令 187
7.3.2 了解NgSwitch指令 187
7.3.3 了解NgFor指令 188
7.3.4 了解<ng-template>标签 189
7.3.5 了解<ng-container>标签 189
7.3.6 实例29:自定义结构型指令 190
第8章 管道 193
8.1 使用管道 193
8.1.1 实例30:使用DatePipe管道 193
8.1.2 实例31:使用UpperCasePipe管道 194
8.1.3 实例32:使用LowerCasePipe管道 194
8.1.4 实例33:使用CurrencyPipe管道 194
8.1.5 实例34:使用PercentPipe管道 195
8.2 对管道进行参数化 195
8.3 链式管道 196
8.4 自定义管道 196
第9章 动画 198
9.1 实例 35:一个动画的例子 198
9.1.1 初始化应用 198
9.1.2 准备工作 199
9.1.3 创建组件 199
9.1.4 运行效果 200
9.2 状态与转场 200
9.2.1 *状态 201
9.2.2 void状态 202
9.3 进场与离场 202
9.4 Animatable属性与单位 203
9.5 自动属性值计算 204
9.6 动画时间线 205
9.6.1 持续时间 205
9.6.2 延迟 205
9.6.3 缓动函数 205
9.6.4 实例36:动画时间线的例子 205
9.7 基于关键帧的多阶段动画 207
9.7.1 什么是关键帧和偏移量 207
9.7.2 实例37:基于关键帧的多阶段动画 207
9.8 并行动画组 209
9.9 动画回调 210
第10章 表单 212
10.1 模板驱动 212
10.1.1 实例38:创建表单 213
10.1.2 实例39:绑定数据 217
10.1.3 实例40:提交表单 219
10.2 用户输入 222
10.2.1 实例41:绑定用户输入 223
10.2.2 实例42:通过$event对象取得用户输入 224
10.2.3 实例43:从一个模板引用变量中获得用户输入 225
10.2.4 实例44: Enter键事件 225
10.2.5 实例45:失去焦点事件 226
10.3 表单验证 227
10.3.1 模板驱动验证 227
10.3.2 响应式表单验证 228
10.3.3 自定义验证器 231
10.3.4 自定义样式 233
10.3.5 跨字段交叉验证 234
10.4 响应式表单 236
10.4.1 实例46:响应式表单的例子 236
10.4.2 管理控件的值 239
10.4.3 实例47:表单控件分组的例子 240
10.4.4 实例48:嵌套的表单组的例子 243
10.4.5 使用patchValue()方法更新部分模型 246
10.4.6 使用FormBuilder 246
10.4.7 使用FormBuilder时的表单验证 248
10.4.8 实例49:使用FormArray管理动态控件的例子 249
10.5 动态表单 251
10.5.1 动态表单的优势 251
10.5.2 实例50:动态表单的例子 252
第4篇 高阶 260
第11章 使用Observable与RxJS实现响应式编程 260
11.1 了解Observable机制 260
11.1.1 了解基本概念 260
11.1.2 定义观察者 261
11.1.3 执行订阅 262
11.1.4 创建Observable对象 263
11.1.5 实现多播 264
11.1.6 处理错误 267
11.2 了解RxJS技术 268
11.2.1 创建Observable对象的函数 268
11.2.2 了解操作符 269
11.2.3 处理错误 271
11.3 了解Angular中的Observable 272
11.3.1 EventEmitter 273
11.3.2 HTTP 273
11.3.3 AsyncPipe 274
11.3.4 Router 274
11.3.5 响应式表单 275
11.4 对比Observable对象和Promise 276
11.4.1 创建与订阅 276
11.4.2 串联 277
11.4.3 可取消 277
11.4.4 错误处理 277
11.4.5 总结对比结果 277
11.5 对比Observable对象和事件API 278
11.6 对比Observable对象和数组 279
第12章 Angular模块 281
12.1 模块概述 281
12.1.1 什么是模块化 281
12.1.2 认识基本模块 282
12.1.3 认识特性模块 283
12.2 引导启动 283
12.2.1 了解declarations数组 284
12.2.2 了解imports数组 285
12.2.3 了解providers数组 285
12.2.4 了解bootstrap数组 285
12.3 常用模块 285
12.3.1 常用模块概述 285
12.3.2 BrowserModule和CommonModule 286
12.4 特性模块分类 286
12.4.1 领域特性模块 286
12.4.2 带路由的特性模块 287
12.4.3 路由模块 287
12.4.4 服务特性模块 288
12.4.5 可视部件特性模块 288
12.5 入口组件 288
12.5.1 引导用的入口组件 288
12.5.2 路由用的入口组件 289
12.5.3 entryComponents数组 289
12.5.4 entryComponents数组和编译器 290
12.6 服务提供商 290
12.6.1 创建和提供服务 290
12.6.2 服务提供商的作用域 291
12.6.3 providedIn与NgModule 291
12.6.4 使用惰性加载模块限制服务提供商的作用域 291
12.6.5 使用组件限定服务提供商的作用域 292
12.6.6 选择模块中的服务还是组件中的服务 292
12.7 单例服务 293
12.7.1 提供单例服务 293
12.7.2 了解forRoot() 293
12.7.3 如何防止重复导入CoreModule 294
12.8 共享模块 295
12.8.1 实例51:共享模块的例子 295
12.8.2 使用来自其他模块的组件和服务 296
12.9 惰性加载的特性模块 296
12.9.1 实例52:惰性加载特性模块 296
12.9.2 了解forRoot()与forChild() 300
第13章 依赖注入 301
13.1 初识依赖注入 301
13.2 实例53:在Angular中实现依赖注入 302
13.2.1 初始应用 303
13.2.2 创建服务 305
13.2.3 理解注入器 305
13.2.4 理解服务提供商 308
13.2.5 注入服务 312
13.2.6 单例服务 313
13.2.7 组件的子注入器 313
13.2.8 测试组件 314
13.2.9 服务依赖服务 314
13.2.10 依赖注入令牌 315
13.2.11 可选依赖 315
13.3 多级依赖注入器 315
13.3.1 注入器树 316
13.3.2 注入器冒泡 316
13.3.3 在不同层级再次提供同一个服务 316
13.3.4 组件注入器 316
第14章 通过HTTP访问网络资源 318
14.1 初识HttpClient 318
14.2 认识空气质量数据资源 318
14.3 实例54:使用HttpClient 320
14.3.1 导入HttpClient 320
14.3.2 编写空气质量组件 321
14.3.3 编写空气质量服务 321
14.3.4 注入服务到组件中 322
14.3.5 返回带类型检查的响应 324
14.3.6 读取完整的响应体 325
14.4 实例55:错误处理 327
14.4.1 获取错误详情 327
14.4.2 重试 328
14.5 实例56:请求非JSON格式的数据 329
14.6 实例57:发送数据到服务器 330
14.6.1 添加请求头 330
14.6.2 发起POST请求 330
14.6.3 发起DELETE请求 331
14.6.4 发起PUT请求 331
14.7 高级用法 331
14.7.1 实例58:配置请求 331
14.7.2 实例59:请求去抖 332
14.7.3 实例60:拦截请求和响应 333
14.7.4 实例61:监听进度 334
14.8 XSRF防护 335
14.8.1 了解XSRF防护 335
14.8.2 实例62:实现XSRF防护 335
14.9 实例63:测试HTTP请求 336
14.9.1 采用Mock方式 336
14.9.2 设置环境 336
14.9.3 期望并回复请求 337
14.9.4 测试对错误的预期 337
第15章 路由与导航 339
15.1 路由器的作用 339
15.2 基础知识 339
15.2.1 设置<base>标签关联应用目录 339
15.2.2 从路由库中导入路由器 340
15.3 实例64:配置路由器 340
15.3.1 配置路由器 340
15.3.2 输出导航生命周期中的事件 342
15.4 实例65:设置路由出口 342
15.5 理解路由器链接 343
15.5.1 路由器状态 343
15.5.2 激活的路由 343
15.6 路由事件 344
15.7 重定向URL 345
15.8 实例66:一个路由器的例子 346
15.8.1 创建应用及组件 346
15.8.2 修改组件的模板 346
15.8.3 导入并设置路由器 346
15.8.4 添加路由出口 347
15.8.5 美化界面 348
15.8.6 定义通配符路由 350
第16章 测试 352
16.1 测试准备 352
16.2 认识测试工具 353
16.2.1 认识Jasmine和Karma 354
16.2.2 配置Jasmine和Karma 355
16.2.3 启用代码覆盖率报告 355
16.2.4 了解测试工具API 356
16.3 理解组件测试 357
16.3.1 实例67:单独测试组件类 357
16.3.2 测试组件DOM 360
16.4 实例68:测试服务 361
16.4.1 测试普通服务 362
16.4.2 测试带有依赖的服务 362
16.4.3 测试HTTP服务 363
16.5 实例69:测试属性型指令 364
16.6 实例70:测试管道 366
16.7 调试测试程序 367
第17章 实现国际化 369
17.1 国际化概述 369
17.2 实例71:通过i 18n工具来实现国际化 369
17.2.1 使用i 18n属性 370
17.2.2 在i18n属性中添加描述 370
17.2.3 在i 18n属性中添加意图 370
17.2.4 创建翻译源文件 371
17.2.5 了解翻译源文件 372
17.2.6 创建翻译文件 372
17.2.7 增加应用配置 373
17.2.8 运行应用 374
17.3 实例72:通过ngx-translate插件实现国际化 375
17.3.1 添加ngx-translate库 375
17.3.2 导入并配置ngx-translate模块 375
17.3.3 注入TranslateService服务 376
17.3.4 编写翻译文件 377
17.3.5 使用ngx-translate 378
17.3.6 运行应用 379
第18章 编译与部署Angular应用程序 380
18.1 编译Angular应用程序 380
18.1.1 编译概述 380
18.1.2 编译分类 380
18.1.3 为什么需要AOT编译 381
18.2 了解Angular模板编译器选项 381
18.3 理解Angular元数据与AOT 385
18.3.1 理解元数据的限制 385
18.3.2 理解AOT的工作原理 385
18.4 部署Angular应用程序 386
18.4.1 最简化的部署方式 386
18.4.2 为生产环境准备的部署方式 387
第19章 页面静态化 389
19.1 Universal概述 389
19.1.1 了解Universal 389
19.1.2 使用Universal的好处 389
19.2 初始化Universal示例 390
19.3 实例73:使用Universal 390
19.3.1 安装工具 390
19.3.2 修改根模块 AppModule 391
19.3.3 创建AppServerModule模块 391
19.3.4 创建main文件 392
19.3.5 创建AppServerModule配置文件 392
19.3.6 创建新的构建目标并打包 393
19.3.7 设置服务器环境 393
19.3.8 打包并运行应用 395
第20章 启用缓存 397
20.1 了解Service Worker 397
20.2 实例74:使用Service Worker 398
20.2.1 添加service-worker包 398
20.2.2 用http-server启动服务器 399
20.2.3 模拟网络故障 400
20.2.4 查看缓存内容 400
20.2.5 修改应用 402
20.2.6 在浏览器中更新应用 402
20.3 了解Service Worker的通信机制 403
20.3.1 有可用更新和己激活更新 404
20.3.2 检查更新 404
20.3.3 强制激活更新 405
20.4 配置Service Worker 405
第5篇 商业实战 409
第21章 新闻头条客户端总体设计 409
21.1 应用概述 409
21.2 需求分析 409
21.2.1 首页需求分析 409
21.2.2 新闻详情页面需求分析 410
21.3 架构设计 411
21.3.1 获取访问API的密钥 411
21.3.2 了解新闻API 412
21.4 实例75:初始化新闻头条客户端应用 414
21.4.1 修改app.component.html 414
21.4.2 修改app.component.ts 414
21.4.3 启动应用 415
第22章 实现新闻头条客户端首页 416
22.1 首页需求分析 416
22.2 首页架构设计 416
22.3 实例76:实现新闻头条客户端首页 416
22.3.1 添加Angular Material 417
22.3.2 配置动画 417
22.3.3 导入组件模块 417
22.3.4 包含一个主题 417
22.3.5 创建组件 418
22.3.6 实现界面原型 418
22.3.7 查看完整的首页原型效果 422
第23章 实现新闻头条客户端导航栏 424
23.1 导航栏概述 424
23.2 导航栏需求分析 424
23.3 导航栏架构设计 424
23.4 实例77:实现新闻头条客户端新闻分类 425
23.4.1 新建新闻分类服务 425
23.4.2 解析新闻分类数据 425
23.4.3 展示新闻分类 426
23.5 实例78:实现新闻头条客户端新闻列表 427
23.5.1 新建新闻列表服务 427
23.5.2 解析新闻列表数据 428
23.5.3 展示新闻列表 430
23.6 实例79:实现新闻分类与新闻列表组件通信 433
23.6.1 监听导航栏单击事件 433
23.6.2 自定义导航切换事件 433
23.6.3 监听导航切换事件 434
23.6.4 运行应用 435
第24章 实现新闻头条客户端新闻详情页面 436
24.1 新闻详情页面概述 436
24.2 新闻详情页面需求分析 436
24.3 新闻详情页面架构设计 437
24.4 实例80:实现新闻头条客户端新闻详情页面 437
24.4.1 新建新闻详情组件及服务 437
24.4.2 获取新闻详情数据 437
24.4.3 展示新闻详情 438
24.4.4 创建首页组件 439
24.4.5 创建路由器 439
24.4.6 修改新闻列表组件 440
24.4.7 接收路由参数 441
24.4.8 增加“返回”按钮 442
24.4.9 运行应用 442
参考文献 444