-
Notifications
You must be signed in to change notification settings - Fork 1
/
Typed Forms in Angular-L-odCf4MfJc.cn.vtt
603 lines (410 loc) · 14.1 KB
/
Typed Forms in Angular-L-odCf4MfJc.cn.vtt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
WEBVTT
Kind: subtitles
Language: zh-CN
00:00:00.000 --> 00:00:09.881
[音乐播放]
00:00:09.881 --> 00:00:14.310
大家好,Angular 社区
00:00:14.310 --> 00:00:15.673
我叫 Dylan Hunn
00:00:15.673 --> 00:00:18.740
是 Angular 框架团队的一名软件工程师
00:00:18.740 --> 00:00:20.020
在过去的八个月里
00:00:20.020 --> 00:00:22.430
我们一直致力于改进 Angular 表单
00:00:22.430 --> 00:00:26.480
非常高兴今天能与你分享这项新功能
00:00:26.480 --> 00:00:30.115
类型化表单是 Angular 14 的一部分
00:00:30.115 --> 00:00:33.750
今天就可以开始迁移你的应用程序了
00:00:33.750 --> 00:00:35.328
在深入细节之前
00:00:35.328 --> 00:00:38.400
让我们先了解一下响应式表单的背景知识
00:00:38.400 --> 00:00:42.556
对于构建或维护表单应用程序的人来说
00:00:42.556 --> 00:00:44.580
这可能已经很熟悉了
00:00:44.580 --> 00:00:48.466
响应式表单是在 Angular 中
构建表单的一种方式
00:00:48.380 --> 00:00:50.543
与模板驱动的表单相比
00:00:50.543 --> 00:00:57.033
它们使用 RxJS 和 Observables 提供了更
明确的数据模型和状态管理
00:00:56.930 --> 00:00:59.150
它们并不总是正确的选择
00:00:59.150 --> 00:01:01.791
模板驱动的表单不那么冗长
00:01:01.791 --> 00:01:04.010
对于某些场景来说会更合适
00:01:04.010 --> 00:01:08.222
我们今天要看到的这些新类型
仅适用于响应式表单
00:01:08.130 --> 00:01:10.450
这是我们要注意的地方
00:01:10.450 --> 00:01:12.590
让我们从一些背景开始
00:01:12.590 --> 00:01:19.722
了解为什么要进行这种更改以及它如何使
大多数使用响应式表单的应用程序受益
00:01:19.620 --> 00:01:20.413
长期以来
00:01:20.413 --> 00:01:24.908
类型化表单一直是 Angular 社区中
投票最多的功能请求
00:01:24.820 --> 00:01:28.790
此外,此更改为许多未来的改进扫清了道路
00:01:28.790 --> 00:01:35.365
例如更好的控件状态变更事件、
更严格的模板类型检查等等
00:01:35.240 --> 00:01:36.987
在设计类型化表单时
00:01:36.987 --> 00:01:39.350
我们试图遵循一个大方向
00:01:39.350 --> 00:01:42.900
特别是,我们有四项指导原则
00:01:42.900 --> 00:01:45.650
首先,我们希望它是强类型的
00:01:45.650 --> 00:01:50.356
你应该能够自信地修改任何复杂表单
00:01:50.356 --> 00:01:54.820
无论你的表单组或表单控件的嵌套有多深
00:01:54.820 --> 00:01:58.450
其次,我们不想完全取代原有的表单
00:01:58.450 --> 00:02:03.689
我们希望拥有一个协同前行的统一生态系统
00:02:03.570 --> 00:02:06.329
第三,我们希望表单尽可能安全
00:02:06.329 --> 00:02:08.201
当你访问值或控件时
00:02:08.201 --> 00:02:11.650
你的类型中的任何内容都不会让人吓一跳
00:02:11.650 --> 00:02:12.247
第四
00:02:12.247 --> 00:02:16.190
你应该能够按照自己的步调逐步迁移
00:02:16.190 --> 00:02:20.850
哪怕你的应用程序中有很多现有的表单代码
00:02:20.850 --> 00:02:23.970
现在我们来考虑一个例子
00:02:23.970 --> 00:02:27.187
通常,每个表单都对应一个模式
00:02:27.187 --> 00:02:30.060
或者说你要收集的数据的形态
00:02:30.060 --> 00:02:33.030
这是代表派对的示例架构
00:02:33.030 --> 00:02:40.733
它具有内部对象(这里是地址字段)和
内部数组(这里是派对菜单)
00:02:40.620 --> 00:02:44.421
没必要总是显式声明你的架构
00:02:44.421 --> 00:02:49.270
但在处理复杂表单时考虑一下还是有好处的
00:02:49.270 --> 00:02:53.180
这里我们就明确声明了表单模型
00:02:53.180 --> 00:02:57.280
这是举办派对的相应表单
00:02:57.280 --> 00:03:04.502
它接受各方地址、菜单以及你可能需要的任
何其他表单控件的输入
00:03:04.380 --> 00:03:10.320
以前,与这么复杂的表单模型交互可能很危险
00:03:10.320 --> 00:03:13.380
例如,这段代码就包含一个微妙的错误
00:03:13.380 --> 00:03:19.689
place 的值为 number,在其上调用 substring 将在运行时崩溃
00:03:19.580 --> 00:03:21.593
现在,有了类型化表单
00:03:21.593 --> 00:03:25.821
这个错误在编译时就会被你的编辑器捕获
00:03:25.720 --> 00:03:28.660
这些新类型渗透到各种 API 中
00:03:28.660 --> 00:03:39.068
在访问表单值、获取深层嵌套控件、订阅 Observables
等几乎任何与表单 API 交互的点时
00:03:39.068 --> 00:03:41.174
你都会从中受益
00:03:41.050 --> 00:03:43.520
这将大大提高安全性
00:03:43.520 --> 00:03:47.810
防止简单的拼写错误和更复杂的错误
00:03:47.810 --> 00:03:53.223
这些类型还允许在你的编辑器中使用强大的
自动完成功能
00:03:53.110 --> 00:03:57.190
在派对表单示例中,当访问表单的值时
00:03:57.190 --> 00:04:00.670
IDE 会建议表单的每个已知子项
00:04:00.670 --> 00:04:05.680
这有助于你自信地浏览最复杂的表单
00:04:05.680 --> 00:04:08.294
虽然这是一个很大的变化
00:04:08.294 --> 00:04:12.500
但它 100% 向后兼容所有现有的表单代码
00:04:12.500 --> 00:04:15.361
当你更新到 Angular 14 时
00:04:15.361 --> 00:04:18.680
你的表单将自动排除这些新类型
00:04:18.680 --> 00:04:20.927
然后,当你准备就绪时
00:04:20.927 --> 00:04:24.410
你可以每次在一个控件上打开它们
00:04:24.410 --> 00:04:27.219
并按照自己的步调逐步迁移
00:04:27.220 --> 00:04:30.225
现在你已经掌握了基础知识
00:04:30.225 --> 00:04:32.750
让我们探索实际的类型
00:04:32.750 --> 00:04:36.760
好,刚才我们看到了一个建立派对的模式
00:04:36.760 --> 00:04:41.664
现在让我们看一下与该派对的表单相对应的
一些实际代码
00:04:41.570 --> 00:04:43.348
让我们进入模板
00:04:43.348 --> 00:04:46.810
我们将添加一个用于举办派对的新按钮
00:04:46.810 --> 00:04:50.170
我们将调用 partyInSF 便捷函数
00:04:50.170 --> 00:04:53.460
现在我们将跳转到相应的组件
00:04:53.460 --> 00:04:57.481
我们将添加用于举办派对的便捷函数
00:04:57.480 --> 00:05:00.870
我们将从所在组件访问 this.party
00:05:00.870 --> 00:05:04.020
这对应于所有参与者数据的表单组
00:05:04.020 --> 00:05:09.822
我们将调用此表单组的 setValue 以赋予其新值
00:05:09.690 --> 00:05:13.650
但是,请注意我们这里忘了写门牌号
00:05:13.650 --> 00:05:16.906
TypeScript 会警告我们这里缺少一个键
00:05:16.906 --> 00:05:19.891
因为它期望当我们调用一个设置值时
00:05:19.891 --> 00:05:21.610
组中的所有键都存在
00:05:21.610 --> 00:05:23.080
好,让我们继续添加它
00:05:23.080 --> 00:05:25.073
请注意,在我键入时
00:05:25.073 --> 00:05:29.390
新的 TypeScript 类型也支持自动完成功能
00:05:29.390 --> 00:05:31.360
但是,我这里仍然有错误
00:05:31.360 --> 00:05:34.240
类型系统不只是检查缺失的属性
00:05:34.240 --> 00:05:39.620
它还会检查对象中的所有名称和所有类型
00:05:39.620 --> 00:05:41.247
特别是在这里
00:05:41.247 --> 00:05:43.639
虽然我目前有一个名为 number 的键
00:05:43.639 --> 00:05:45.840
但我想要的是名为 house 的键
00:05:45.840 --> 00:05:49.350
另一种选择是改为对值打补丁(patch)
00:05:49.350 --> 00:05:52.819
这仍然可以保护我们免受严重的类型错误
00:05:52.819 --> 00:05:56.100
但放宽了要求我们拥有全部键的约束
00:05:56.100 --> 00:05:59.250
特别是,我们要有 street 键
00:05:59.250 --> 00:06:01.270
现在让我们考虑另一种情况
00:06:01.270 --> 00:06:03.044
假设一位邻居投诉了噪音
00:06:03.044 --> 00:06:05.280
我们想弄清楚是哪个邻居投诉的
00:06:05.280 --> 00:06:08.700
那我们就可以在组件上添加一个新方法
00:06:08.700 --> 00:06:10.491
我们可以使用 get 方法
00:06:10.410 --> 00:06:15.839
get 方法接受一个字符串并将自动标记
字符串中的每个字段
00:06:15.839 --> 00:06:17.950
允许我们访问内部控件
00:06:17.850 --> 00:06:20.580
请注意类型是正确计算的
00:06:20.580 --> 00:06:23.217
在这种情况下,我们实际上又出现了错误
00:06:23.217 --> 00:06:26.777
那是因为我们正在尝试用字符串进行算术运算
00:06:26.700 --> 00:06:30.480
这个错误告诉我们应该使用 house 键
00:06:30.480 --> 00:06:31.740
而不是 number
00:06:31.740 --> 00:06:35.211
现在你已经近距离观察了这些新类型
00:06:35.211 --> 00:06:38.051
让我们深入了解设计细节
00:06:38.050 --> 00:06:38.535
接下来
00:06:38.535 --> 00:06:42.120
请考虑我们刚才看到的用于地址的表单组
00:06:42.120 --> 00:06:46.681
本例中 address.controls 的类型应该是什么?
00:06:46.681 --> 00:06:47.658
另一方面
00:06:47.658 --> 00:06:51.024
address.value 的类型应该是什么?
00:06:51.024 --> 00:06:52.870
使用类型化表单时
00:06:52.870 --> 00:06:56.888
了解值类型与控件类型之间的区别很重要
00:06:56.780 --> 00:06:59.867
正如我们之前在派对示例中看到的那样
00:06:59.867 --> 00:07:01.190
值就是数据的形态
00:07:01.190 --> 00:07:06.300
例如,在这里,street 字段的类型为字符串
00:07:06.300 --> 00:07:09.750
另一方面,你也可以访问控件
00:07:09.750 --> 00:07:13.197
在这里,street 字段是一个表单控件
00:07:13.197 --> 00:07:15.150
其中有一个字符串
00:07:15.150 --> 00:07:18.190
类型化表单大量使用控件类型
00:07:18.190 --> 00:07:21.613
虽然你很少需要指定显式类型
00:07:21.613 --> 00:07:23.515
但如果你这样做
00:07:23.515 --> 00:07:26.431
你应该始终使用控件类型
00:07:26.430 --> 00:07:30.570
另一个有趣的话题是重置控件
00:07:30.570 --> 00:07:35.200
让我们考虑最简单的形式,只有一个控件
00:07:35.200 --> 00:07:37.215
当我们考虑这个控件时
00:07:37.215 --> 00:07:39.230
我们首先看到它包含一个字符串
00:07:39.230 --> 00:07:43.130
所以我们可能期望类型是字符串的表单控件
00:07:43.130 --> 00:07:46.060
但是,有一个棘手的细节
00:07:46.060 --> 00:07:48.355
当你使用表单控件时
00:07:48.355 --> 00:07:50.650
你可以随时调用重置
00:07:50.650 --> 00:07:52.955
当发生这种情况时
00:07:52.955 --> 00:07:56.480
控件的值将立即重置为 null
00:07:56.480 --> 00:08:01.729
这意味着你不能总是假设控件的值是一个字符串
00:08:01.610 --> 00:08:04.253
在以前的 Angular 版本中
00:08:04.253 --> 00:08:06.566
此示例会在运行时崩溃
00:08:06.566 --> 00:08:09.760
因为你无法对空值调用子字符串
00:08:09.760 --> 00:08:14.352
Angular 14 现在可以保护你免受此类错误
的影响
00:08:14.352 --> 00:08:18.332
因为此示例中狗控件的类型是字符串或空值
00:08:18.230 --> 00:08:22.520
但有时,这实际上并不是你想要的行为
00:08:22.520 --> 00:08:23.401
事实上
00:08:23.401 --> 00:08:29.696
许多现有形式的应用程序并不依赖于控件的
现有可空性
00:08:29.570 --> 00:08:31.227
在 Angular 14 中
00:08:31.227 --> 00:08:35.418
表单控件有一个名为 nonNullable 的全新选项
00:08:35.320 --> 00:08:37.899
控件不会重置为 null
00:08:37.899 --> 00:08:40.350
而是重置为其初始值
00:08:40.350 --> 00:08:41.508
如你所料
00:08:41.508 --> 00:08:45.110
这还会从控件类型中删除 null
00:08:45.110 --> 00:08:48.540
在这个例子中,我们已经完全摆脱了空值
00:08:48.540 --> 00:08:53.070
现在调用 substring 是完全安全的
00:08:53.070 --> 00:08:58.900
相关领域涉及禁用控件及其对表单值的影响
00:08:58.900 --> 00:09:00.861
对于 Angular 表单
00:09:00.861 --> 00:09:04.020
禁用的控件不包含在表单的值中
00:09:04.020 --> 00:09:09.653
这类似于原生 HTML 表单在其控件被禁用时
的行为方式
00:09:09.540 --> 00:09:13.650
但是,这会影响表单的类型
00:09:13.650 --> 00:09:15.342
当你调用 .value 时
00:09:15.342 --> 00:09:18.840
表单组中的任何键都可能已被禁用
00:09:18.840 --> 00:09:22.590
结果,该类型知道每个键都是可选的
00:09:22.590 --> 00:09:24.730
当你使用此值时
00:09:24.730 --> 00:09:31.293
类型系统会强制你处理每个键都可能未定义的情况
00:09:31.150 --> 00:09:34.830
在此示例中,当使用 cat.value 时
00:09:34.830 --> 00:09:38.747
cat 表单组中的所有字段都是可选的
00:09:38.747 --> 00:09:41.240
因为它们可能已被禁用
00:09:41.240 --> 00:09:41.835
然而
00:09:41.835 --> 00:09:47.309
这并不是我们可能在表单中使用可选键的唯
一情况
00:09:47.190 --> 00:09:51.460
有时你希望能够自由地从表单中删除键
00:09:51.460 --> 00:09:51.992
例如
00:09:51.992 --> 00:09:56.140
这里我们对名称 name 调用 removeControl
00:09:56.140 --> 00:09:57.819
使用类型化表单
00:09:57.819 --> 00:10:01.736
我们现在可以明确指定哪些键是可选的
00:10:01.736 --> 00:10:03.191
哪些是必选的
00:10:03.190 --> 00:10:09.624
这允许类型系统强制我们安全地处理
可能丢失的控件
00:10:09.490 --> 00:10:11.785
对于完全动态的表单组
00:10:11.785 --> 00:10:15.173
你希望在其中添加或删除许多控件
00:10:15.173 --> 00:10:20.419
我们还引入了一种名为 FormRecord 的全新
伴随类型
00:10:20.310 --> 00:10:23.584
这里的类型改进是广泛而深入的
00:10:23.584 --> 00:10:26.180
还有更多值得兴奋的地方
00:10:26.180 --> 00:10:33.658
你可以在 angular.io 上提供的新增
《类型表单》指南中深入阅读它们
00:10:33.658 --> 00:10:36.191
并在下面的描述中链接
00:10:36.070 --> 00:10:40.448
我们对 Angular 14 和类型化表单的未来
感到非常兴奋
00:10:40.360 --> 00:10:46.221
我们希望你和我们一样对这个项目和
整个表单包的未来感到兴奋
00:10:46.120 --> 00:10:48.430
请点赞和订阅,感谢你的收看
00:10:48.430 --> 00:10:49.180
下次见
00:10:49.180 --> 00:10:52.230
[音乐播放]