编辑推荐
8 g; W e% t9 p; U * 强力的IDE支持+完善的生态圈+一套代码、多种平台+……=Angular* 知名全栈开发工程师经验总结- _% j/ l2 i7 G% F% N2 L1 {1 ^& t$ a
* 雪狼组织的Nice Angular社区主力倾情翻译
8 e& z. x2 Q! Y t% Z: {# A# f * Google推荐阅读
+ K- T9 ]0 r" u- U; D5 U: m 本书内容循序渐进,帮你在短时间内毫不费力地掌握整个Angular框架并打好坚实的基础,工作效率获得极大的提升。' b B) Z! U7 L. r( C" d
书中包含丰富的示例应用,展示如何编写组件、如何使用表单和API,还会带你学习如何使用Angular创建:+ s, [! U; J3 ^$ F* Z
- 基于组件的仿制版Reddit
" c6 }# m7 x2 s- r - 使用RxJS可观察对象的实时聊天应用/ w2 t- F2 X) |/ _. Z( f$ D4 Z, b
- “随敲随搜”的YouTube搜索应用
) I$ q) {4 r0 _8 g: Z6 s: t8 ] - 带有可播放乐曲预览的Spotify曲目搜索应用内容简介" I9 P( G" p+ a! B
本书堪称Angular领域的里程碑式著作,涵盖了关于Angular的几乎所有内容。对于没有经验的人,本书平实、通俗的讲解,递进、严密的组织,可以让人毫无压力地登堂入室,迅速领悟新一代Web应用开发的精髓。如果你有相关经验,那本书对Angular概念和技术细节的全面剖析,以及引人入胜、切中肯綮的讲解,将帮助你彻底掌握这个框架,在自己职业技术修炼之路上更进一步。
7 d$ I8 o8 y/ x" ? 作者简介
6 |5 w6 M5 P$ h Ari Lerner$ U) R4 W: z- K' l* ~% i! C5 }
全栈工程师,拥有多年Angular经验,自办并运营Angular电子报ng-newsletter.com,在知名硅谷工程师培训学校Hack Reactor担任AngularJS讲师。Fullstack.io创始人。: d! v% _( y# T _2 m
Felipe Coury
: n) q* \5 W0 L' ?6 d& R2 T9 _- X9 X Gistia Labs联合创始人兼CTO。2 x+ }/ G/ c" `; v
Nate Murray7 v% o$ {$ N' ?0 d; I6 T; }0 [6 b
全栈工程师,曾任职于IFTTT,拥有数据挖掘和增量Web服务等方面的背景。 `) s3 p- H" B+ W
Carlos Taborda
6 l8 k$ t. q+ h, f Gistia Labs联合创始人兼主管。9 i! M( K, A3 W. g$ ]! s
目录& P7 Z2 O7 z+ l% h0 k6 |9 Z
第1章 编写你的第一个Angular Web应用 11.1 仿制Reddit网站 1
$ e3 z3 L" D- q9 B; ?+ [ 1.2 起步 3
: F7 R3 t% Z0 w# I5 R8 m 1.2.1 TypeScript 3' Y4 L, Z4 f$ |6 f4 r
1.2.2 angular-cli 33 B( g4 T% B% ?+ F" `6 ~& v% v
1.2.3 示例项目 4( R9 \2 u& h; f8 A
1.3 运行应用 7
+ y+ Q6 u% n. {9 V& J 1.3.1 制作Component 88 _2 H9 P. F! {8 J i
1.3.2 导入依赖 9# @& N, U9 ^$ {- \7 @7 G7 U/ `
1.3.3 Component注解 10
3 v& g/ V4 [' c; u+ `7 P+ T 1.3.4 用templateUrl添加模板 11
' i. I7 @) Y5 x; a8 d- F 1.3.5 添加template 11) N* Q$ b/ {7 |2 r
1.3.6 用styleUrls添加CSS样式 123 o9 |, M3 K2 X& v; L
1.3.7 加载组件 120 ]5 R4 l/ U9 q5 ?, Y0 N
1.4 把数据添加到组件中 13
0 @. W; ^! Q% _ 1.5 使用数组 15
: I( t2 |9 V( c: b5 z; N 1.6 使用UserItemComponent组件 18* y E# E, ~+ w/ l4 j5 }8 e
1.6.1 渲染UserItemComponent 18, b, R7 f1 L5 @4 q
1.6.2 接收输入 196 Z& T& [& w. a" x: ~# M! n8 V
1.6.3 传入Input值 20, N+ z! Q5 x) Q: K6 D' w
1.7 “启动”速成班 21
! H2 w& \+ q5 K# P: o: R 1.8 扩展你的应用 22
4 M7 m' A) E0 B/ s# R9 Y 1.8.1 添加CSS 245 n. X4 l \$ ~6 K
1.8.2 应用程序组件 24: \! T! i: \1 M- s6 |5 k
1.8.3 添加互动 26" U% ~, W# \8 m3 i T
1.8.4 添加文章组件 29
: N( z2 c& O" A( i4 _ 1.9 渲染多行 36
5 H4 A: B2 \. d" G 1.9.1 创建Article类 36
0 G0 M$ X2 v, c% ~7 B 1.9.2 存储多篇文章 40& X. I, `- w: b
1.9.3 使用inputs配置ArticleComponent 411.9.4 渲染文章列表 42
: ^5 L8 F) x. ^& q' }' o 1.10 添加新文章 44+ ~- V4 F: I! {5 z2 j
1.11 最后的修整 44
, `' f8 m8 M, |3 }+ c" h6 G. i 1.11.1 显示文章所属的域名 44- q H* D2 O; r
1.11.2 基于分数重新排序 45 A* S$ T- I' s+ x" w7 G$ h
1.12 全部代码 45
* c" m1 F; k4 a. F } 1.13 总结 45$ C" U% q. {6 I0 |9 ^; B1 ?
1.14 获得帮助 46+ ^4 _+ [2 N8 H' q
第2章 TypeScript 47
: U! d# ^7 y/ ?7 j$ t/ g* h 2.1 Angular是用TypeScript构建的 47
{) D! ]/ J, o/ C 2.2 TypeScript提供了哪些特性 48
( z/ h' [+ g8 H) @8 a 2.3 类型 493 B B7 q# P% e0 R) E
2.4 内置类型 504 r* v/ \& s7 |
2.4.1 字符串 50* l1 d) L# G9 F" `$ ~* D8 o
2.4.2 数字 50" C6 Q2 r i. j! h
2.4.3 布尔类型 51
" T5 Y: m9 _) \& u 2.4.4 数组 51
* }2 Q# _( Z; Q 2.4.5 枚举 51
( U9 R, y) ^: C1 k4 s, t 2.4.6 任意类型 52 C6 W* o2 b! f3 y4 r
2.4.7 “无”类型 52
# _4 J1 U8 d A2 O4 I# j% I1 H 2.5 类 52* o' h' `2 `' Z; ~0 }: H- [
2.5.1 属性 52* }, C4 B( S6 X0 w
2.5.2 方法 53, W' s% A f0 t
2.5.3 构造函数 54
6 J: }% d9 k) I( {" u 2.5.4 继承 55
. [ m0 c3 \5 n: } 2.6 工具 57
, B0 N8 [' _' f) Y* d) N* y 2.6.1 胖箭头函数 57
% X! O" V2 ~9 b6 @ 2.6.2 模板字符串 581 a1 d* a. ^$ D4 g3 F, M
2.7 总结 59
% t$ h7 P' C2 ?4 M0 _; c 第3章 Angular的工作原理 60
+ ]" V- m* D! L% P+ f) L 3.1 应用 60
$ |3 e8 w8 @# y6 H: V, _, |- s 3.1.1 主导航组件 611 H1 {$ m, g7 f* G- W
3.1.2 面包屑导航组件 61& b3 Y4 G5 l! A
3.1.3 产品列表组件 62" A5 d: _9 F4 a
3.2 产品数据模型 64
* p" ^0 W( w/ Z" N' Y" w, g 3.3 组件 64
: Y9 Q5 x1 D( U2 o) f 3.4 组件注解 66
1 ?3 ^$ m, q) m 3.4.1 组件selector 664 ?: a" s6 [0 y+ Y8 w
3.4.2 组件template 67
6 O* G% c5 c Y( P& g0 i8 F 3.4.3 添加产品 67" L O7 l" i( v; K
3.4.4 用模板绑定来查看产品 680 j4 g8 o/ L6 p6 R
3.4.5 添加更多产品 691 `7 U- Z( `( |
3.4.6 选择一个产品 700 ]# V- Z! ]: t3 y2 a8 I' E
3.4.7 用列出产品 73 [" P1 I$ j/ m2 P4 M
3.5.1 设置ProductsList的@Component配置项 733.5.2 组件的输入 743 K# X0 F/ b/ m7 _ j3 }4 |
3.5.3 组件的输出 771 ] r! o2 \5 w. K* t
3.5.4 触发自定义事件 78
* V) Y* |! L( Z W% |) ?5 [/ s2 u 3.5.5 编写ProductsList的控制器类 79
2 G8 K5 a* ~" v% {5 S3 }/ I 3.5.6 编写ProdctsList的视图模板 814 ~4 N: d" G4 H/ A( K
3.6 产品条目组件 83- h! S+ |( P) I% K
3.6.1 产品条目的组件配置 83: ]# e+ }- E) z* I& @; `# L m: t# o/ `
3.6.2 产品条目组件的定义类 84
& w" g& i& a( i! d6 \! T3 ] 3.6.3 产品条目组件的template 84
! ?4 b& p5 M6 O+ Y+ T* X' ^ 3.6.4 完整的ProductRow代码清单 85
, p5 d( p7 K! |+ }7 a2 H- \9 _ 3.8 价格展示组件 86
% ~' ]. M8 E0 T$ E c( x 3.9 产品分类组件 87
( e% t, \* r$ T- t9 R+ f' X 3.10 创建NgModule并启动应用 88
' ?9 K; h- G5 ^7 ? 3.11 完整的项目 89
. n7 X b7 ?! `7 h 3.12 关于数据架构的一点说明 90# |4 j6 @0 O, J: [# P+ d S6 F
第4章 内置指令 91( V: W4 b% }& z
4.1 简介 91
$ s7 F4 s: O0 F/ P 4.2 ngIf 91
( D% t; a5 Q# M9 c& b 4.3 ngSwitch 924 g, Q9 z" s. i$ U
4.4 ngStyle 934 f) G" b; h2 u3 H1 ~ Z' d. ~8 q
4.5 ngClass 95
. }2 H1 K ^% s% Y3 T6 v5 Q! K/ q" ?/ E 4.6 ngFor 98- s% Q0 o* @/ c& J' p- f& `
4.7 ngNonBindable 102
0 q0 c% C& W T+ r: w" a' ~3 _ 4.8 总结 102, s0 H5 [3 a7 o% N4 D
第5章 Angular中的表单 1036 k+ O l1 T6 m9 L" }8 p1 o
5.1 表单——既重要,又复杂 1031 Z& Z& Y" Z, u0 p( k! P' e# ]
5.2 FormControl和FormGroup 103
x/ | G( V* |, ^$ r 5.2.1 FormControl 1049 P0 ~6 K2 i/ B& z% R0 {' @' J
5.2.2 FormGroup 104
. o9 S, g8 W+ y+ [ 5.3 我们的第一个表单 105
3 y/ q- M @" g* E 5.3.1 加载FormsModule 106( i( W9 l5 E, s1 P R
5.3.2 简易SKU表单:@Component注解 1075.3.3 简易SKU表单:template 107! y# _+ b- Z0 ^! ^
5.3.4 简易SKU表单:组件定义类 110
. V0 y3 B! M* q! L0 f 5.4 使用FormBuilder 111+ ?. u4 y! r7 F" n; ~' _8 L. D& G
5.5 响应式表单 FormBuilder 112
$ [: o# Q) v' B) h( W9 R; ? 5.5.1 使用FormBuilder 112
# }/ L2 ?. j3 } 5.5.2 在视图中使用myForm 113& ^% F0 q- K4 P8 K$ s. x
5.5.3 试试看 114
" M, b9 f' O# G 5.6 添加验证 1152 E$ v) L h. \4 [# ]# G& \& M; K
5.6.1 显式地把sku设置为实例变量 116# r5 z- b* `% F6 s# T$ U
5.6.2 自定义验证器 120
3 {; Q: b6 O$ Q$ n8 P 5.7 监听变化 121 j* A1 z8 X4 ]/ s& p1 E
5.8 ngModel 122
5 ^6 X/ g9 f9 c 5.9 总结 124' `8 v/ f/ m1 p1 t
第6章 HTTP 125. k$ T$ o# B2 E" m) t' p
6.1 简介 125
/ n$ } V& j7 L. U5 j4 @. F# w 6.2 使用@angular/http 126
+ V- A! ~. D9 A% ?7 P6 i 6.3 基本请求 127$ J: y- | G7 I/ y+ p
6.3.1 构建SimpleHTTPComponent的@Component 1276.3.2 构建SimpleHTTPComponent的template 1286.3.3 构建SimpleHTTPComponent控制器 1286.3.4 完整的SimpleHTTPComponent 130( |' S' u6 ~# M' G' V5 v: ^
6.4 编写YouTubeSearchComponent 130
% H n( a) [& g* U 6.4.1 编写SearchResult 132* U8 J; h2 U. O* {) g
6.4.2 编写YouTubeService 132
+ d2 Z! v; ?9 |) @ M' J 6.4.3 编写SearchBox 140& e7 A' k5 z4 x, }( U" c- q
6.4.4 编写SearchResultComponent 145: [# a! y, l( `5 u3 }) |3 U
6.4.5 编写YouTubeSearchComponent 1472 u7 W/ F. g2 q; e4 |/ ]! s
6.5 @angular/http API 1506 x" h+ e, N, E
6.5.1 发起一个POST请求 150
" u9 R7 Q/ F/ c 6.5.2 PUT/PATCH/DELETE/HEAD 150
, L8 w/ \. M- \# ?! @4 R$ D8 ~) l$ D& n1 o% P 6.5.3 RequestOptions 151, Y5 z9 N' |% J) ~; E' ^
6.6 总结 151
: W6 P% A( J3 G- ?) v4 t 第7章 路由 1521 o' j5 l( [$ N; P
7.1 为什么需要路由 1526 G7 b* M3 e; H% {+ Z2 h- t0 n* \# D1 x
7.2 客户端路由的工作原理 153/ d9 E2 z9 s. N! |! g: e
7.2.1 初级阶段:使用锚标记 153 I5 R8 b# G) o+ g _4 f
7.2.2 进化:HTML5客户端路由 154
1 q8 b; T9 k$ z& J$ E$ z 7.3 编写第一个路由配置 155
+ l7 X; w* a, B0 y' Q+ a7 ] 7.4 Angular路由的组成部件 155! P2 R6 U: v0 Q
7.4.1 导入 155
: r3 L- e/ c6 m0 D' ~ 7.4.2 路由配置 155# [/ ?6 a. R9 |* u7 N" F5 J4 j
7.4.3 安装路由配置 156, }* x! p9 T9 f1 L6 A9 P
7.4.4 使用调用RouterOutlet指令 157+ I) w7 v7 h- {! c* u8 A: x+ x
7.4.5 使用[routerLink]调用routerLink指令 1587.5 整合 1599 X$ U& H, T2 x3 Z/ q
7.5.1 创建组件 160
9 r/ R- N0 x9 ~3 l 7.5.2 应用程序组件 161. Z% r4 t- p, ~8 n9 d- I
7.5.3 配置路由 163/ O1 u( b4 N& x2 W) O
7.6 路由策略 164
* G9 u! o" c$ I2 Y; X* B 7.7 路径定位策略 165, ^5 |; S8 j; ^$ g6 j; C
7.8 运行应用程序 165
! a# F6 r/ I5 H, q, S 7.9 路由参数 167
: M* e8 }! D2 Y6 h 7.10 音乐搜索应用 168
# Q& X5 m+ H: c8 M' ` 7.10.1 首要步骤 1699 B: A0 I8 S: W/ d( p
7.10.2 SpotifyService 170
T5 J2 `& k2 v5 H$ R0 Z h$ s 7.10.3 SearchComponent 171
s6 a+ J+ N3 x3 g8 k* y$ ?9 n 7.10.4 尝试搜索 179. D# ^, f, f# x3 H/ n' t* \* M x
7.10.5 TrackComponent 180- Z. i% i0 p( N& b D8 O" a, G
7.10.6 音乐搜索应用小结 182
' \5 `' W) F* b0 d8 L4 l 7.11 路由器钩子 182
" F$ ` v& @+ C4 e8 w 7.11.1 AuthService 183! t m$ R; \; g8 U/ X" l4 O
7.11.2 LoginComponent 184
3 q% a( o8 @- s4 Q5 ?$ P/ { 7.11.3 ProtectedComponent组件和路由守卫 1867.12 嵌套路由 190! ^) \2 d$ E4 M; u/ L, t4 ?
7.12.1 配置路由 191; x1 `0 b s& Y; {$ f) A6 Y5 O
7.12.2 ProductsComponent组件 191" N8 p+ Z0 n- i9 Q
7.13 总结 194$ @+ F r/ {! o: V& S+ g5 }5 }2 B
第8章 依赖注入 195
$ N" d1 x6 f# k$ ^/ b! d( b, \ 8.1 注入示例:PriceService 196
* _9 E, h% s( J 8.2 “别打给我们……” 197* e/ ?; i" r5 d
8.3 依赖注入的部件 1999 B% n7 e3 G1 |# K# V5 j
8.4 尝试注入器 2003 m% E2 E, p: B# k" Y
8.5 用NgModule提供依赖 201
N! M8 \; `. ~/ l/ d 8.6 提供者 202) O' e9 W. r/ c. X* G, ?
8.6.1 使用类 202
0 B& U% T- ]+ ~7 [- F4 n4 ] 8.6.2 使用工厂 203
( L' H2 e8 L0 q" u7 V& N8 e 8.6.3 使用值 205
, a$ [6 \: G9 x, t. S7 }6 x 8.6.4 使用别名 2056 Y! q7 \5 V! b* A% i
8.7 应用中的依赖注入 205. S/ j1 A% [. i8 j! F9 u) u
8.8 使用注入器 207
) o! \! j4 g* m2 {# I2 s5 G 8.9 替换值 211
3 l+ T# p( _* a! r6 s, p8 g 8.10 NgModule 215
$ _3 Z* c" P0 ~+ b8 r8 b* l9 E* G0 ` 8.10.1 NgModule与JavaScript模块 215
6 f+ t. F( N8 W" e, s* ~ 8.10.2 编译器与组件 2150 {1 X }8 ^8 j% N4 m6 g% G) z
8.10.3 依赖注入与提供者 216
+ i& {7 f+ X5 R( s$ }3 s6 T! t1 Z1 D 8.10.4 组件可见性 217
0 Q% u2 B# Z( M# p 8.10.5 指定提供者 2183 D; h- J+ g+ l$ w0 `9 C- {
8.11 总结 219
0 t% u0 i" @+ J6 f% @6 p8 Z 第9章 Angular数据架构 220- d2 T7 N. `% M* A3 i, U& s
第10章 使用可观察对象的数据架构,第1 部分:服务 22210.1 可观察对象和RxJS 222
8 ^' |: G, j/ |. g8 } 10.1.1 注意:一些必备的RxJS相关知识 22210.1.2 学习响应式编程和RxJS 2231 q% }6 E* w# g7 @# |
10.2 聊天应用概览 224
2 I" D8 J7 [/ G9 t* K3 i W 10.2.1 组件 225; l3 R i5 t; U; T
10.2.2 数据模型 2265 V5 G3 w+ V# i
10.2.3 服务 2260 n1 y. r1 O8 ^. x8 M. B
10.2.4 总结 226+ F7 |& D e8 n% r3 y3 M
10.3 实现数据模型 2278 C7 X( m; ?" B, o1 K# r
10.3.1 User 2270 N! [' X0 c4 Y/ I9 ? ] f6 j: F; [. g# `) v
10.3.2 Thread 227
* C& K/ o5 M- X$ l9 [2 b0 h 10.3.3 Message 2282 M N6 j6 u$ V) O9 s$ o
10.4 实现UserService 228! X$ y, i' P: V" V2 T' s# g1 L
10.4.1 currentUser流 229 o5 p9 C* A' y# x6 p+ Q+ \
10.4.2 设置新用户 2309 k$ E# s- h4 I5 F5 Y' P
10.4.3 UserService.ts 231
1 ~1 u! M/ I( }5 K/ I- V. M9 U5 q 10.5 MessagesService 2317 V8 O, m( u* A5 ~$ l
10.5.1 newMessages流 231) V; s J' O$ M! |$ n6 m8 ^$ |
10.5.2 messages流 233; I( `4 a+ x8 T" w- ~' s
10.5.3 操作流模式 233
0 u2 W. m4 X) h- e& C6 } 10.5.4 共享流 2349 M' W8 @8 n4 K5 T
10.5.5 把Message对象添加到messages流中 23510.5.6 完整的MessagesService 238% k( r) L( h( Y" E6 h
10.5.7 试用MessagesService 241% {: w( `+ p4 Q/ i* I
10.6 ThreadsService 242- }" K4 H2 Q* [3 j! C
10.6.1 当前一组Thread 的映射(threads流) 24210.6.2 按时间逆序排列的Thread列表(orderedthreads流) 24610.6.3 当前已选的Thread(currentThread流) 24610.6.4 当前已选Thread的Message列表(currentThreadMessages流) 24810.6.5 完整的ThreadsService 250# k/ [7 c B* `! v& Q% o
10.7 总结 251
3 U( h/ @" O) g, T8 k. M0 p 第11章 使用可观察对象的数据架构,第2部分:视图组件 25211.1 构建视图:顶层组件ChatApp 252! d, j9 |8 q6 {# |8 X4 T, K0 c
11.2 ChatThreads组件 254
( L' b! y1 c( L) |$ h 11.2.1 ChatThreads控制器 255+ o( V# @8 L# d( s, |
11.2.2 ChatThreads的template 256- F0 o2 p( [3 ~) G8 o
11.3.1 ChatThread控制器和ngOnInit 25711.3.2 ChatThread的template 258% R8 V2 U8 Z$ r6 ^/ V
11.3.3 ChatThread的完整代码 258
/ h3 h; P5 u; q( s& O' U 11.4 ChatWindow组件 259 W- o2 P0 M. W5 ]! \: a
11.4.1 ChatWindow组件类属性 260: \& L, v) a( U1 w2 W3 v; v
11.4.2 ChatWindow的ngOnInit 2616 w9 }2 Y" c) S3 l' p G$ @- V
11.4.3 ChatWindow的sendMessage 261
! I( {! n& u" w 11.4.4 ChatWindow的onEnter 262
/ z( V R4 ?; c. D& { 11.4.5 ChatWindow的scrollToBottom 26211.4.6 ChatWindow 的template 263
}% c! k/ I3 n' N& L 11.4.7 处理键盘动作 264
% s0 U+ `1 d. g& N, u3 x 11.4.8 使用ngModel 264
1 O0 b. ]! S1 _6 p+ E 11.4.9 点击Send按钮 265
0 \) D. j. X, L7 A5 x 11.4.10 完整的ChatWindow组件 267
4 e% j* o: K5 d# ?/ g, {% n 11.5.1 设置incoming属性 2685 j6 `( |" \* P a3 y
11.5.2 ChatMessage的template 270
3 w1 ? L/ ~) d5 ^5 U% f' a 11.6 ChatNavBar组件 2735 p) H+ Y, e6 r& p0 v, [
11.6.1 ChatNavBar的@Component 273
# p7 m5 v+ q' o# B 11.6.3 ChatNavBar的template 274
2 `# ]% Q2 w9 g. Y8 f5 ?, ?$ X U 11.6.4 完整的ChatNavBar组件 275' { H" i$ E7 L4 A6 |2 @
11.7 总结 276
- Q( f/ M% o3 d% |6 f 11.8 更进一步 277
. G4 s( ~! b7 C& e+ R 第12章 基于TypeScript的Redux简介 278
3 U' M" Y8 t( T6 k0 e 12.1 Redux 2793 \' Q* Q+ D d* @8 M0 M3 Z6 N$ c
12.2 Redux核心概念 280
6 ^+ X- g5 [) @+ `% f) S 12.2.1 reducer是什么 280 C- ]; s8 K) B0 J
12.2.2 定义Action和Reducer的接口 281$ N2 z4 U$ Y9 r h( @2 u
12.2.3 创建第一个Reducer 281# Z* }4 m+ z D8 ~* b/ A; _2 l
12.2.4 运行第一个Reducer 2827 T3 Z1 P0 [# [. {
12.2.5 使用action调整计数器 283. F. _, M3 }+ \" ^
12.2.6 reducer的switch 284
! i. A& F) E: i# y4 L: L 12.2.7 action的“参数” 2855 k( a1 Y9 A; s7 T N6 m V
12.3 保存state 286
2 I2 a9 q2 X$ N, Z# U2 F' | 12.3.1 使用store 287
7 ?; A6 h( ]: K 12.3.2 使用subscribe进行通知 287: W/ t4 n Y. f+ s0 R) P
12.3.3 Redux核心 2906 i: D$ ]( G# E* p2 R
12.4 消息应用 2918 k$ ]# [& X( S9 H
12.4.1 消息应用的state 291
, G U6 _2 t% J5 \0 {5 T% Q& ] 12.4.2 消息应用的action 2924 k( H$ k) K4 l% B! M
12.4.3 消息应用的reducer 292# L" x3 s! A8 R2 _2 y. C
12.4.4 试用action 295
+ s e# X3 f) j; t( V 12.4.5 action creator 296) D9 O6 T+ M' f; V1 m
12.4.6 使用真正的Redux 297
6 n) `* l8 g2 ]7 R a* Y 12.5 在Angular中使用Redux 299- G) ~9 R4 A% }. M. W
12.6 规划应用 299$ X3 T% t, o( q
12.7 组建Redux 300/ t6 s. ]! n* e- E3 z
12.7.1 定义应用的state 300
. N7 {/ e- q- `) K7 Q! H/ Z 12.7.2 定义reducer 301 i" Z4 v; p& J* a7 ]+ ?7 U/ e4 a
12.7.3 定义action creator 301
+ d# f6 _) m) | 12.7.4 创建store 3023 r3 Q1 P* H8 s0 P) l# g) `
12.8 CounterApp组件 303! V0 M5 D; [: @+ e. e$ U
12.9 提供store 304
. a0 U/ r0 a/ D. _6 [ i+ k6 X 12.10 启动应用 305
/ o. g3 _* C3 @! u$ ?9 m3 d b 12.11 CounterComponent 3067 `$ C* O5 [, A; s1 i# u# X
12.11.1 import 3068 U+ v3 k, F4 M+ y7 m
12.11.2 模板 306* t7 p$ T9 A8 f% `# M
12.11.3 constructor 307& `" r y; ` x( y7 d2 U
12.11.4 整合 308
7 ^4 e6 W9 ?9 w# e 12.12 更进一步 310+ T9 i1 m( y" d. z" @
12.13 参考资源 310 \8 |) |9 f" S j
第13章 在Angular中引入Redux 312& S/ Z7 g8 \7 y5 Q4 N8 q' Z
13.1 阅读背景 3123 ^8 R/ V" K3 q3 Y0 Z/ R
13.2 聊天应用概览 313% S: D# f+ L, F- [
13.2.1 组件 313* z& w; i( H2 c1 e
13.2.2 数据模型 314
& j& k6 g0 O# `5 {: ^6 { 13.2.3 reducer 315
9 b; {0 K, N3 V; a4 y 13.2.4 总结 315* z; k% T, i( n2 S% l
13.3 实现数据模型 315- a7 O5 D3 l- E2 f3 U
13.3.1 User 315
1 l+ X$ C2 ?# b) S& b( ^ 13.3.2 Thread 316
$ O1 H$ B; @6 _2 z% D: X4 [8 w0 Y 13.3.3 Message 3162 k% h7 I) C$ ?4 @# F. P, d
13.4 应用的state 3161 `( N$ x: S3 {) K* P. ]3 r
13.4.1 关于代码布局 317$ ^+ P8 R9 |# G# E& j
13.4.2 根reducer 317
$ _, y" M5 |1 `9 n' { 13.4.3 UserState 318, s1 B7 a4 R) F
13.4.4 ThreadsState 318
; J2 M+ @* Y1 w/ _( Y- S* N; P 13.4.5 可视化AppState 319
7 @5 s' t8 }0 J w/ Q 13.5 构建reducer(和action creator) 32113.5.1 设置当前用户的action creator 32113.5.2 UsersReducer:设置当前用户 32113.5.3 会话和消息概览 322* r& Y! P2 {1 S% |( }
13.5.4 添加新会话的action creator 32213.5.5 添加新会话的reducer 323
! N) G: j) e( U 13.5.6 添加新消息的action creator 32413.5.7 添加新消息的reducer 325
, U5 A7 E! S" }) N 13.5.8 选择会话的action creator 326- X" ]+ k* O; m/ g, ?8 G
13.5.9 选择会话的reducer 327# h9 s* t* s+ A
13.5.10 reducer总结 3280 w4 a s9 {% Y2 ]2 B( A2 B/ U% R
13.6 构建Angular聊天应用 328- ?6 v# H K. y6 _6 H
13.6.1 顶层组件ChatApp 330" c8 j8 f, l e! f
13.6.2 ChatPage 330
6 K& `. c" @. L# R 13.6.3 容器型组件与展示型组件 332; }. |+ r4 P7 J; d
13.7.1 Redux选择器 334 K. B0 _0 s$ o; N5 t% ?8 F: n8 L
13.7.2 会话选择器 334
% t5 x8 I. j! w, B$ ]- O3 h+ u 13.7.3 未读消息总数选择器 3363 E& A. k9 D# Y7 X' {2 h
13.8 构建ChatThreads组件 336
, u- }( O' d3 o# l 13.8.1 ChatThreads控制器 3377 T F0 ~% | M6 p D1 q
13.8.2 ChatThreads的template 338
4 o) _( [1 k- t) z 13.10 构建ChatWindow组件 3401 T2 u6 ?3 R1 c8 n
13.10.1 ChatWindow的updateState() 34113.10.2 ChatWindow的scrollToBottom() 34213.10.3 ChatWindow的sendMessage 3422 W7 G$ Y7 B- E' B c. Z" ~
13.10.4 ChatWindow的onEnter 343+ T1 ?' ]$ j* P8 D$ l7 k, ?/ \' w$ V8 ]
13.10.6 处理键盘动作 345
6 q. ^! a# o; r/ X) J 13.10.7 使用ngModel 345
8 n& @6 W* L% a' e/ M- S 13.10.8 点击Send按钮 3452 a+ r4 [. S0 o: q+ [
13.11 ChatMessage组件 345
/ i u5 n( e4 y- w 13.11.1 设置incoming属性 346
' M& ^; ?% w$ @; ]) Z 13.11.2 ChatMessage的template 346, G3 A6 q0 u# G' n/ C
13.12 总结 3475 h4 R2 ]0 P5 a; d8 T
第14章 高级组件 349
1 {: V* |2 s/ g 14.1 样式 349
* [ |, ~0 @& u 14.1.1 视图(样式)封装 3515 R7 E: k I y) g: Z! X! V9 G
14.1.2 Shadow DOM 封装 354 |" u- A4 l4 I& J
14.1.3 不使用封装 355/ W; [% ~! V7 O1 A+ n9 r: U1 N
14.2 创建popup指令:引用并修改宿主元素 35714.2.1 popup指令的结构 3577 W( I. Z8 r! H f6 n5 [$ r* l
14.2.2 使用ElementRef 359
. x. E+ T s% Z* ^4 ` 14.2.3 绑定到host属性 360
/ L; r) ~2 B) P3 Z/ ~ 14.2.4 添加按钮并使用exportAs 363+ F" S: x9 Q9 E, ]' O
14.3.1 改变host属性的CSS类 364
! j3 ~7 a6 |0 y5 Y/ @- q' T 14.3.2 使用ng-content 364# M* f3 h+ h4 ?2 p) w; _
14.4 查询相邻的指令:编写标签页 366. R! G" {! K: B; o ^! B. F4 e' o
14.4.1 Tab组件 367# J o v3 T8 _% m9 n! j
14.4.2 Tabset组件 367
9 K D1 w( D3 }9 U9 q" C" A 14.4.3 使用Tabset 369
. n% a e% P; h6 K' N2 B* j 14.5 生命周期钩子 370% J- k6 [# m0 r9 E2 U
14.5.1 OnInit和OnDestroy 3710 T: k! F) }; _
14.5.2 OnChanges 374% ?/ {0 l6 R5 L& ^3 Y
14.5.3 DoCheck 3788 X2 p/ W8 g. Q* {
14.5.4 AfterContentInit、AfterViewInit、AfterContentChecked和AfterViewChecked 38614.6 高级模板 391
6 u. c0 b6 Q, u8 A2 q2 c2 \3 ]; [ 14.6.1 重写ngIf:ngBookIf 392& m6 ?) x9 P& d2 C2 k& L
14.6.2 重写ngFor:ngBookRepeat 394
. h3 F; z& n0 f 14.7 变更检测 398; a; ~* l1 n% ]7 x/ a* F. E" r
14.7.1 自定义变更检测 401
1 N7 |' [( z- W& E, v1 Y) R8 `; a 14.7.2 Zones 405
0 C0 q+ A8 r" }& q 14.7.3 可观察对象和OnPush 406, W$ g6 V/ w" Z+ y6 f. ~* ^* o
14.8 总结 4099 D1 b' j% {$ Q* |( L$ P/ m# G
第15章 测试 410
; X, H U1 S& B9 k$ D6 H r9 e/ k" B8 K 15.1 测试驱动? 410
: y+ Z1 e+ P" h, J2 N9 k 15.2 端对端测试与单元测试 411 t$ _3 K0 r! x7 o; o
15.3 测试工具 4117 C8 J' [) e: H
15.3.1 Jasmine 411
- o" M, j* k' ? 15.3.2 Karma 412& k. ~! J) q, E4 K) e7 U
15.4 编写单元测试 412
, o! b! x/ i( o5 ? 15.5 Angular单元测试框架 412
. S$ ]# Q& B F. _! v7 l 15.6 测试前准备 413
! R9 S: r0 O9 U. Z* C- } 15.7 测试服务类和HTTP 415
" `2 N3 l+ u; C! @8 D0 Q 15.7.1 HTTP要点 416
0 w, i' p) G* {1 i2 w# j 15.7.2 伪装 417" a0 j& e/ K9 _; l
15.7.3 模拟 417
/ {. {3 [6 o0 ~6 Z9 g8 \$ Z5 W 15.7.4 Http MockBackend 4187 C0 F9 g) E# ?; X9 B$ V
15.7.5 TestBed.configureTestingModule和提供者 41815.7.6 测试getTrack方法 419
2 M0 O' m! F. s @8 H1 Y5 I 15.8 测试组件间的路由 4241 i, Y8 L5 I0 t) H* `
15.8.1 为测试创建路由器 424& `2 U5 b. n) B" {5 W
15.8.2 模拟依赖 427# H7 |7 M4 L0 z; K7 Y/ B" y+ c
15.8.3 探子 4275 R8 q& y& ^: \- w) t' C7 {) t" L O
15.9 回到测试代码 4291 @7 z$ [& w. |+ H. u. f; B
15.9.1 fakeAsync和advance 431
1 u( j! w% ^+ F6 `% A 15.9.2 inject 432/ \5 I c2 m7 }5 }8 h! b ?5 M3 p6 ]4 B
15.9.3 测试ArtistComponent组件初始化 43215.9.4 测试ArtistComponent方法 433
/ @' f" q4 }! b* C) _8 ^ 15.9.5 测试ArtistComponent DOM模板值 43415.10 测试表单 436
! ]+ m' i2 \2 C& J& [# j, V$ f& T 15.10.1 创建一个ConsoleSpy 438
2 q L' N2 ]0 p, @- L7 x8 [ N 15.10.2 安装ConsoleSpy 439
@9 f/ X) ?' ~: D% M& N 15.10.3 配置测试模块 4391 e! S9 c6 E. X9 P/ K
15.10.4 测试表单 440
9 ]7 }5 c; H' x$ e- y. x8 l 15.10.5 重构表单测试 441
9 y: L( P' h/ N% A! N7 a" j 15.11 测试HTTP请求 444
7 v9 _( t; x4 n: ]5 v 15.11.1 测试POST方法 445, z% h2 u9 @# ]7 A5 b2 o! _
15.11.2 测试DELETE方法 446
' V, @5 M* s* z0 p6 U7 K 15.11.3 测试HTTP头 4473 L2 |6 |! k. A, |5 G5 T
15.11.4 测试YouTubeService 448: K- ?, U5 x$ b
15.12 总结 452
" ~! w" \: h. ^: C 第16章 把AngularJS应用升级到Angular 45316.1 周边概念 453
3 D! L( W( ^7 F) A: x' @; j" j 16.2 我们要构建什么 454& j5 X+ S/ r P/ O
16.3 把AngularJS映射到Angular 455
( d) P- a- H) ^- a2 Z 16.4 关于互操作性的需求 456
0 _3 h+ }1 _. }5 ~7 P s+ q0 F 16.5 AngularJS应用 456
6 x; {2 d+ T' M% w& {( K4 V% {, L 16.5.1 AngularJS应用的HTML 458
9 N! `% F' Y0 N6 f$ M 16.5.2 代码概览 4587 u- d3 r8 d4 ]7 ]8 e; i8 T( H
16.5.3 AngularJS:PinsService 459( y' K a n+ n9 N* o
16.5.4 AngularJS:配置路由 460
- m* O9 J1 C* x; S 16.5.5 AngularJS:HomeController 461/ A/ {6 s- q p6 Z- b( `: U: U, [
16.5.6 AngularJS:HomeController模板 46116.5.7 AngularJS:pin指令 462
! ^6 e: X/ P& x# |1 t# j! {) E4 S 16.5.8 AngularJS:pin指令模板 4639 _, Q4 Q: H! I- }0 \7 L
16.5.10 AngularJS:AddController模板 46516.5.11 AngularJS:总结 467
. H$ b0 e4 l: L9 D6 f ?7 y* p 16.6 构建混合式应用 468
$ f3 R) |3 D6 y D6 ~4 i 16.6.1 混合式应用的结构 468 O- y3 Q7 f7 A/ |( o. A! Q5 t
16.6.2 引导混合式应用 471/ `* O- k5 C" [1 s4 J: F8 E$ v" b
16.6.3 我们要升级什么 473
0 a# l$ x) t+ }) X& X3 r 16.6.4 插一小段内容:类型文件 479
- g! D& r8 |1 E H. G. O) Z 16.6.6 使用Angular的PinControlsComponent 48116.6.7 把Angular的PinControlsComponent 降级到AngularJS 48216.6.8 用Angular添加图钉 483
4 R# g3 T, ]. i 16.6.9 把AngularJS的PinsService和$state升级到Angular 48416.6.10 写Angular版的AddPinComponent 48516.6.11 使用AddPinComponent 490
, D- ?/ o; L% c 16.6.12 把Angular的服务暴露给AngularJS 49016.6.13 实现AnalyticsService 491$ n0 s" J$ I& c, b2 \9 ^
16.6.14 把Angular的AnalyticsService降级到AngularJS 49216.7 总结 4935 m+ c: U8 Q" l* \4 b
16.8 参考资源 493
d& A# z& T4 E1 A" l
5 _1 N( r$ v* I; s( v Z$ z* e( \- \+ M4 V+ r" i* E3 ~$ y% N* r
|