-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
813 lines (730 loc) · 126 KB
/
Copy pathatom.xml
File metadata and controls
813 lines (730 loc) · 126 KB
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
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Angular2 知识梳理</title>
<link href="//angular.github.io/atom.xml" rel="self"/>
<link href="https://github.com/tuluffy/"/>
<updated>2017-08-01T08:01:03.000Z</updated>
<id>https://github.com/tuluffy/</id>
<author>
<name>tuluffy</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>Angular 2(十): websocket</title>
<link href="https://github.com/tuluffy/2017/08/01/websocket/"/>
<id>https://github.com/tuluffy/2017/08/01/websocket/</id>
<published>2017-08-01T08:01:03.000Z</published>
<updated>2017-08-01T08:01:03.000Z</updated>
<content type="html"><![CDATA[<h3 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h3><ul>
<li>服务器端的socket和客户端的服务中的socket保持长连接,进行数据交换;</li>
<li>客户端中的服务(socket)作为”被观察者”,客户端中的组件作为观察者;</li>
<li>被观察者通过依赖注入,被注入到组件中;</li>
</ul>
<p>组件订阅socket产生的流,当流发生变化时,组件就会产生相应的事务。</p>
<h4 id="websocket-ts"><a href="#websocket-ts" class="headerlink" title="websocket.ts"></a>websocket.ts</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">export class WebSocketService{</div><div class="line"> ws: WebSocket;</div><div class="line"> </div><div class="line"> createObservableSocket(url:string):Observable<any>{</div><div class="line"> this.ws = new WebSocket(url);</div><div class="line"> </div><div class="line"> return new Observable(observer=>{</div><div class="line"> //指定什么时候派发数据:当后端返回数据时</div><div class="line"> this.ws.onmessage = (event)=>observer.next(event.data);</div><div class="line"> </div><div class="line"> //指定错误发生时如何处理</div><div class="line"> this.ws.onerror = (evevt)=>observer.error(event);</div><div class="line"> </div><div class="line"> //指定关闭时如何处理</div><div class="line"> this.ws.onclose = (event)=>observer.complete();</div><div class="line"> })</div><div class="line"> };</div><div class="line"> </div><div class="line"> sendMessage(message:string){</div><div class="line"> this.ws.send(message); //向服务器发送数据</div><div class="line"> };</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="component-html"><a href="#component-html" class="headerlink" title="component.html"></a>component.html</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">constructor(private wsServer: WebSocketService){}</div><div class="line"></div><div class="line">ngOnInit(){</div><div class="line"> this.wsServer.createObservableSocket()</div><div class="line"> .subscript(</div><div class="line"> data=>console.log(data); //当流发送过来消息时</div><div class="line"> err=>console.log(err);</div><div class="line"> ()=>console.log('流已经结束');</div><div class="line"> )</div><div class="line">};</div><div class="line"></div><div class="line">sendMessageToServer(){</div><div class="line"> this.wsServer.sendMessage(‘这是从组件向服务器发送的信息!’);</div><div class="line">};</div></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h3 id="概览"><a href="#概览" class="headerlink" title="概览"></a>概览</h3><ul>
<li>服务器端的socket和客户端的服务中的socket保持长连接,进行数据交换;</li>
<li>客户端中的服务(socket)
</summary>
</entry>
<entry>
<title>Angular 2(十): 指令</title>
<link href="https://github.com/tuluffy/2017/08/01/directive/"/>
<id>https://github.com/tuluffy/2017/08/01/directive/</id>
<published>2017-08-01T07:41:32.000Z</published>
<updated>2017-08-01T07:41:32.000Z</updated>
<content type="html"><![CDATA[<p>生成指令命令行:ng g directive directiveName</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line">import { Directive } from "@angular/core";</div><div class="line">import { mobileValidator } from '../validators'; </div><div class="line"></div><div class="line">@Directive({</div><div class="line"> selector:'[ mobile ]',</div><div class="line"> providers:[</div><div class="line"> {</div><div class="line"> provide: NG_VALIDATORS,</div><div class="line"> useValue:mobileValidator,</div><div class="line"> //设置该字段,表示一个token下面可以挂载多个指令</div><div class="line"> multi:true</div><div class="line"> }</div><div class="line"> ]</div><div class="line">})</div><div class="line"></div><div class="line">export class MobileValidatorDirective implements Init{</div><div class="line"> constructor(){}</div><div class="line">}</div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><input type="text" #mobile="ngModel" ngModel name="mobile" (input)="onMobileInput(myForm)"/></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">mobileValid:boolean = true;</div><div class="line">mobileUntouched:boolean = true;</div><div class="line"></div><div class="line">onMobileInput(formData:NgForm){</div><div class="line"> if(formData){</div><div class="line"> //用这两个值来控制错误信息的显示和隐藏</div><div class="line"> this.mobileValid = formData.form.get('mobile').valid;</div><div class="line"> this.mobileUntouched = formData.form.get('mobile').untouched;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<p>生成指令命令行:ng g directive directiveName</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div
</summary>
</entry>
<entry>
<title>Angular 2(八): 表单</title>
<link href="https://github.com/tuluffy/2017/08/01/form/"/>
<id>https://github.com/tuluffy/2017/08/01/form/</id>
<published>2017-08-01T03:28:22.000Z</published>
<updated>2017-08-01T03:28:22.000Z</updated>
<content type="html"><![CDATA[<h3 id="标准HTML表单"><a href="#标准HTML表单" class="headerlink" title="标准HTML表单"></a>标准HTML表单</h3><ul>
<li>相关检测属性:required、partern、min、max</li>
<li>一般写法<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><form action="/register" method="post"></div><div class="line"> <input type="text"/></div><div class="line"></form></div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h3 id="在Angular中,有两种形式的表单:响应式表单、模板式表单"><a href="#在Angular中,有两种形式的表单:响应式表单、模板式表单" class="headerlink" title="在Angular中,有两种形式的表单:响应式表单、模板式表单"></a>在Angular中,有两种形式的表单:响应式表单、模板式表单</h3><h4 id="模板式表单:表单的数据模型是通过组件中的指令隐式创建的。使用这种方式定义表单的数据模型时,受限于HTML语法,模板驱动方式仅适用于一些简单的场景。"><a href="#模板式表单:表单的数据模型是通过组件中的指令隐式创建的。使用这种方式定义表单的数据模型时,受限于HTML语法,模板驱动方式仅适用于一些简单的场景。" class="headerlink" title="模板式表单:表单的数据模型是通过组件中的指令隐式创建的。使用这种方式定义表单的数据模型时,受限于HTML语法,模板驱动方式仅适用于一些简单的场景。"></a>模板式表单:表单的数据模型是通过组件中的指令隐式创建的。使用这种方式定义表单的数据模型时,受限于HTML语法,模板驱动方式仅适用于一些简单的场景。</h4><h4 id="响应式表单:通过编写ts代码而不是HTML来创建底层数据模型。在模型创建之后,可以使用一些特定的指令将模板的HTML元素与底层数据模型连接在一起。"><a href="#响应式表单:通过编写ts代码而不是HTML来创建底层数据模型。在模型创建之后,可以使用一些特定的指令将模板的HTML元素与底层数据模型连接在一起。" class="headerlink" title="响应式表单:通过编写ts代码而不是HTML来创建底层数据模型。在模型创建之后,可以使用一些特定的指令将模板的HTML元素与底层数据模型连接在一起。"></a>响应式表单:通过编写ts代码而不是HTML来创建底层数据模型。在模型创建之后,可以使用一些特定的指令将模板的HTML元素与底层数据模型连接在一起。</h4><h3 id="模板式表单"><a href="#模板式表单" class="headerlink" title="模板式表单"></a>模板式表单</h3><p>在Angular中,标准表单会被自动托管,常规的操作无效。如果希望使用原始表单,只需要在form标签内加上ngNoForm指令即可;<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><form action="/register" method="post" ngNoForm></form></div></pre></td></tr></table></figure></p>
<h4 id="知识梳理"><a href="#知识梳理" class="headerlink" title="知识梳理"></a>知识梳理</h4><ul>
<li><p>#myForm=”ngForm”获取表单对象,myForm.value获取表单的值,取值形式:<div></div></p>
</li>
<li><p>(ngSubmit)=”onSubmit(myform.value)”代替了默认的submit</p>
</li>
<li><p>只能在HTML中操作数据模型,不能在ts中操作</p>
</li>
<li><p>在ngForm上使用双向绑定时,不需要像以往那样[(ngModel)]=”user.name”,改写为:直接在标签中加入ngModel指令,同时指定name属性:name=”username”</p>
</li>
<li><p>如果要在ngmodel上使用组件模板变量,#username=”ngModel”,取值形式:<div></div> </p>
</li>
<li><p>ngForm=>隐式创建FormGroup</p>
</li>
<li><p>ngModel=>隐式创建FormControl</p>
</li>
<li><p>ngModelGroup=>隐式创建FormGroup(嵌入结构,用于将一些字段更好地组织在一起,加入指定的对象中)</p>
</li>
</ul>
<p>模板式表单的写法:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><form #myForm="ngForm" (ngSubmit)="onSubmit(myForm.value)"></div><div class="line"> <div></div><div class="line"> 姓名</div><div class="line"> <input type="text" #username="ngModel" ngModel name="username"/></div><div class="line"> </div></div><div class="line"> </div><div class="line"> <div ngModelGroup="psw"></div><div class="line"> <div></div><div class="line"> 密码</div><div class="line"> <input type="text" #psw_1="ngModel" ngModel name="psw_1"/></div><div class="line"> </div></div><div class="line"> <div></div><div class="line"> 密码</div><div class="line"> <input type="text" #psw_2="ngModel" ngModel name="psw_2"/></div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> <button type="submit">提交</button></div><div class="line"></form></div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">onSubmit(val:any):void{</div><div class="line"> console.log(val); //查看表单的值</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="响应式表单"><a href="#响应式表单" class="headerlink" title="响应式表单"></a>响应式表单</h3><ul>
<li><p>响应式表单不可以使用模板变量,如:#myForm,只能在ts中操作数据模型</p>
</li>
<li><p>FormControl</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">userName:FormControll=new FormControl(); </div><div class="line">//可以指定初始值,userName:FormControll=new FormControl('Default'); </div><div class="line"></div><div class="line">//常规使用</div><div class="line"><input [formControl]="username"/></div><div class="line"></div><div class="line">//如果放在FormGroup中,需要改变写法</div><div class="line"><input formControlName="username"/></div></pre></td></tr></table></figure>
</li>
<li><p>FormGroup</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">//构造函数需要一个对象</div><div class="line">//一般用于创建一组固定的子集,使用key检索</div><div class="line">formModel:FormGroup = new FormGroup({</div><div class="line"> from: new FormControl(),</div><div class="line"> to: new FormControl(),</div><div class="line">});</div></pre></td></tr></table></figure>
</li>
<li><p>FormArray:创建一个可变长度子集</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">//构造函数需要一个数组</div><div class="line">//使用索引值检索</div><div class="line">emails: FormArray = new FormArray([</div><div class="line"> new FormControl(),</div><div class="line"> new FormControl(),</div><div class="line">])</div></pre></td></tr></table></figure>
</li>
</ul>
<p>响应式表单的写法:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div></pre></td><td class="code"><pre><div class="line">//注意(submit)和(ngSubmit)写法的区别</div><div class="line"><form [formGroup]="formModel" (submit)="onSubmit()"></div><div class="line"></div><div class="line"> //通过formControlName将底层数据模型和HTML元素绑定在一起</div><div class="line"> //formControl在FormGroup中的写法</div><div class="line"> <input type="text" formControlName="username"></div><div class="line"> </div><div class="line"> //使用formGroupName将特定的属性存储在指定(dateRange)的对象中</div><div class="line"> <div formGroupName="dateRange"></div><div class="line"> </div><div class="line"> //FormGroup的实例对象通过key(from、to)检索元素</div><div class="line"> 开始日期:<input type="date" formControlName="from"/></div><div class="line"> 结束日期:<input type="date" formControlName="to"/></div><div class="line"> </div></div><div class="line"> </div><div class="line"> <div></div><div class="line"> //绑定到FormArray的实例对象</div><div class="line"> <ul formArrayName="emails"></div><div class="line"> </div><div class="line"> //由于FormArray是可变长度,一般与ngFor搭配使用</div><div class="line"> //this.formModel.get('emails')获取的是一个new FormArray对象,通过.controls取到内部元素集合</div><div class="line"> <li *ngFor="let email of this.formModel.get('emails').controls;let i = index;"></div><div class="line"> </div><div class="line"> //由于FormArray使用的是索引值检索,故使用索引值作为模板的名字</div><div class="line"> //formControlName在此处为输入属性</div><div class="line"> 邮箱:<input type="email" [formControlName]="i"/></div><div class="line"> </li></div><div class="line"> </ul></div><div class="line"> <div (click)="addEmail()">增加一个</div></div><div class="line"> </div></div><div class="line"> <button type="submit">保存</button></div><div class="line"></form></div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div></pre></td><td class="code"><pre><div class="line">//在ts中建立底层数据模型</div><div class="line">formModel:FormGroup = new FormGroup({</div><div class="line"> //formControl在FormGroup中的写法</div><div class="line"> username:new FormControl(),</div><div class="line"> </div><div class="line"> dateRange:new FormGroup({</div><div class="line"> from: new FormControl(),</div><div class="line"> to: new FormControl(),</div><div class="line"> }),</div><div class="line"> </div><div class="line"> emails:new FormArray([</div><div class="line"> new FormControl(),</div><div class="line"> ])</div><div class="line">});</div><div class="line"></div><div class="line">addEmail():void{</div><div class="line"> //通过this.formModel.get('emails')获取的是特定的FormArray的实例对象(类型为对象),需要转换成FormArray类型</div><div class="line"> var emails = this.formModel.get('emails') as FormArray;</div><div class="line"> </div><div class="line"> emails.push(new FormControl());</div><div class="line">}</div><div class="line"></div><div class="line">onSubmit():void{</div><div class="line"> //获取表单的值</div><div class="line"> console.log(this.formModel.value);</div><div class="line">}</div></pre></td></tr></table></figure>
<hr>
<h3 id="特别介绍"><a href="#特别介绍" class="headerlink" title="特别介绍"></a>特别介绍</h3><h4 id="数据类型:FormGroup、FormControl、FormArray"><a href="#数据类型:FormGroup、FormControl、FormArray" class="headerlink" title="数据类型:FormGroup、FormControl、FormArray"></a>数据类型:FormGroup、FormControl、FormArray</h4><h4 id="指令:formGroup、formControl"><a href="#指令:formGroup、formControl" class="headerlink" title="指令:formGroup、formControl"></a>指令:formGroup、formControl</h4><h4 id="指令:formGroupName、formControlName、formArrayName"><a href="#指令:formGroupName、formControlName、formArrayName" class="headerlink" title="指令:formGroupName、formControlName、formArrayName"></a>指令:formGroupName、formControlName、formArrayName</h4><ul>
<li>formGroup和formGroupName用来绑定FormGroup</li>
<li>formControl和formControlName用来绑定FormControl</li>
<li>formArrayName用来绑定FormArray</li>
</ul>
<hr>
<h3 id="Angular表单进阶"><a href="#Angular表单进阶" class="headerlink" title="Angular表单进阶"></a>Angular表单进阶</h3><h4 id="借助Angular内部工具FormBuilder改建表单"><a href="#借助Angular内部工具FormBuilder改建表单" class="headerlink" title="借助Angular内部工具FormBuilder改建表单"></a>借助Angular内部工具FormBuilder改建表单</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line">formModel: FormGroup;</div><div class="line">constructor(public fb:FormBuilder){</div><div class="line"> this.formModel = fb.group({</div><div class="line"> username:[''],</div><div class="line"> mobile:[''],</div><div class="line"> passwords:fb.group({</div><div class="line"> psw_1:[''],</div><div class="line"> psw_2:[''],</div><div class="line"> })</div><div class="line"> })</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="表单校验"><a href="#表单校验" class="headerlink" title="表单校验"></a>表单校验</h4><ul>
<li>标准格式<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">nameValidator(control:AbstractControl):{[key:string]:any}{</div><div class="line"> return null;</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>从标准格式可以看出,校验之后返回的对象为null或者一个key为字符串的对象</p>
<ul>
<li>Angular提供的校验器:Validators.required、Validators.minLength(len)等等<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">//使用自带校验器对username字段进行校验</div><div class="line">//在数据模型中(formModel)</div><div class="line">//校验器以数组的形式出现</div><div class="line">username: ['', [ Validator.required,Validator.minLength(6)] ]</div></pre></td></tr></table></figure>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">onSubmit():viod{</div><div class="line"> let isValid:boolean = this.formModel.get('username').valid;</div><div class="line"> let error:any = this.formModel.get('username').error;</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>自定义校验器</li>
</ul>
<p>对于单独的FormControl检验<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">mobileValidator(control:FormControl):any{</div><div class="line"> let reg = /^[0-9]*$/;</div><div class="line"> let valid = reg.test(control.value);</div><div class="line"> </div><div class="line"> //当校验通过时,返回null,否则返回一个空对象</div><div class="line"> return valid ? null : { mobile:true }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<ul>
<li>注意校验器放置的位置 <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mobile:['', this.mobileValidator]</div></pre></td></tr></table></figure>
</li>
</ul>
<p>对于放在FormGroup内部的FormControl的校验<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">equalPswValidator(group:FormGroup):any{</div><div class="line"> let psw_1:FormControl = group.get('psw_1') as FormControl;</div><div class="line"> let psw_2:FormControl = group.get('psw_2') as FormControl;</div><div class="line"> </div><div class="line"> let valid = ( psw_1.value === psw_2.value );</div><div class="line"> </div><div class="line"> return valid ? null : { equalPsw:{msg:'我是错误提示信息!'} }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<ul>
<li>注意校验器放置的位置和写法:{validator:this.equalPswValidator}<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">passwords:fb.group({</div><div class="line"> psw_1:[''],</div><div class="line"> psw_2:[''],</div><div class="line"> },{validator:this.equalPswValidator})</div></pre></td></tr></table></figure>
</li>
</ul>
<h4 id="异步校验器:"><a href="#异步校验器:" class="headerlink" title="异步校验器:"></a>异步校验器:</h4><p>通过代码模拟http请求处理<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">//只需要修改return语句即可,返回的是一个可观察对象</div><div class="line">return Observable.of(valid? null:{mobile:{msg:'错误信息!'}}}).delay(3000);</div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">mobile:['',mobileValidator,asyncMobileValidator]</div></pre></td></tr></table></figure>
<h4 id="通过校验器可以做到的额外的事"><a href="#通过校验器可以做到的额外的事" class="headerlink" title="通过校验器可以做到的额外的事"></a>通过校验器可以做到的额外的事</h4><ul>
<li>通过校验器方法来控制组件中的提示语句隐藏或者显示:hasError、getError</li>
<li>获取独立的FormControl的校验结果:formModel.hasError(‘mobile’,’mobile’);</li>
<li>获取存在FormGroup内部的FormControl的校验结果:formModel.hasError(‘minLength’,[‘passwords’,’psw_1’]) </li>
<li>获取独立的FormControl校验反馈的信息:formModel.getError(‘mobile’,’mobile’);</li>
<li>④获取存在FormGroup内部的FormControl校验反馈的信息:formModel.getError(‘equalPsw’,’passwords’) ? msg:null;</li>
</ul>
<p>注意方法的第一个参数不是校验器的名称,而是校验器返回来的对象的key,即:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">return valid ? null : { equalPsw:true } 中的 equalPsw</div><div class="line">return valid ? null : { mobile:true } 中的mobile</div></pre></td></tr></table></figure></p>
<p>在④中,如果发生错误,那么将会获取到返回的“错误提示信息”。</p>
<h4 id="完整的代码示例:"><a href="#完整的代码示例:" class="headerlink" title="完整的代码示例:"></a>完整的代码示例:</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><form [formGroup]="formModel" (submit)="onSubmit()"></div><div class="line"> <div></div><div class="line"> 用户名:<input type="text" formControlName="username"/></div><div class="line"> <div [hidden]="!formModel.hasError('minlength','username')"></div><div class="line"> 用户名输入不正确</div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> <div></div><div class="line"> 手机号:<input type="text" formControlName="mobile"/></div><div class="line"> <div [hidden]="!formModel.hasError('mobile','mobile')"></div><div class="line"> <div>{{ formModel.getError('mobile','mobile')?.msg }}</div></div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> <div formGroupName="passwords"></div><div class="line"> <div></div><div class="line"> 密码:<input type="text" formControlName="psw_1"/></div><div class="line"> <div [hidden]="!formModel.hasError('minlength',['passwords','psw_1'])"></div><div class="line"> 密码最小长度不符合要求</div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> <div></div><div class="line"> 确认密码:<input type="text" formControlName="psw_2"/></div><div class="line"> <div [hidden]="!formModel.hasError('equalPsw','passwords')"></div><div class="line"> {{ formModel.getError('equalPsw','passwords')?.msg }}</div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> </div></div><div class="line"> <button type="submit">提交</button></div><div class="line"></form></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line">formModel:FormGroup;</div><div class="line"></div><div class="line"> constructor(fb:FormBuilder){</div><div class="line"> this.formModel = fb.group({</div><div class="line"> username:['',[Validators.required,Validators.minLength(6)]],</div><div class="line"> mobile:['',this.mobileValidator], //发现一个现象,如果此处加上Validators.required,程序会报错</div><div class="line"> passwords:fb.group({</div><div class="line"> psw_1:['',Validators.minLength(8)],</div><div class="line"> psw_2:[''],</div><div class="line"> },{validator:this.equalPswValidator})</div><div class="line"> })</div><div class="line"> }</div><div class="line"></div><div class="line"> mobileValidator(control:FormControl):any{</div><div class="line"> let reg = /^[0-9]*$/;</div><div class="line"> let valid = reg.test(control.value);</div><div class="line"></div><div class="line"> return valid ? null : { mobile:{msg:'手机号码不正确!'} }</div><div class="line"> }</div><div class="line"></div><div class="line"> equalPswValidator(control:FormGroup):any{</div><div class="line"> let psw_1 = control.get('psw_1') as FormControl;</div><div class="line"> let psw_2 = control.get('psw_2') as FormControl;</div><div class="line"></div><div class="line"> let valid = (psw_1.value === psw_2.value);</div><div class="line"></div><div class="line"> return valid ? null : { equalPsw:{msg:'密码错误提示信息!'}}</div><div class="line"> }</div><div class="line"></div><div class="line"></div><div class="line"> onSubmit(){</div><div class="line"> let valid = this.formModel.valid;</div><div class="line"></div><div class="line"> console.log(valid);</div><div class="line"> };</div></pre></td></tr></table></figure>
<h4 id="状态字段"><a href="#状态字段" class="headerlink" title="状态字段"></a>状态字段</h4><ul>
<li><p>touched/untouched:字段是否获取过焦点,如果获取过则:true/false,否则相反;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><div [hidden]="!formModel.get('mobile').valid || formModel.get('mobile').untouched"></div><div class="line"> 当获得过焦点,且表单校验为false,那么显示这段错误提示信息!</div><div class="line"></div></div></pre></td></tr></table></figure>
</li>
<li><p>pristine/dirty:如果一个值未被修改过,则:true/false,否则相反;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><div [hidden]="formModel.get('mobile').valid || formModel.get('mobile').pristine"></div><div class="line"> 当值被修改过,且不合法的情况下显示该提示信息!</div><div class="line"></div></div></pre></td></tr></table></figure>
</li>
<li><p>pending:当一个字段正处于异步校验中时,该字段为true</p>
</li>
</ul>
]]></content>
<summary type="html">
<h3 id="标准HTML表单"><a href="#标准HTML表单" class="headerlink" title="标准HTML表单"></a>标准HTML表单</h3><ul>
<li>相关检测属性:required、partern、min、max</li>
<li
</summary>
</entry>
<entry>
<title>Angular 2(九): 服务</title>
<link href="https://github.com/tuluffy/2017/07/31/http/"/>
<id>https://github.com/tuluffy/2017/07/31/http/</id>
<published>2017-07-31T02:35:51.000Z</published>
<updated>2017-07-31T02:35:51.000Z</updated>
<content type="html"><![CDATA[<p>Angular的http服务返回的是Observable(可观察数据流),通过订阅来获取可用数据。</p>
<p>订阅方式有:手动订阅(subscript)、异步管道订阅(async)</p>
<h4 id="手工订阅"><a href="#手工订阅" class="headerlink" title="手工订阅"></a>手工订阅</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><div *ngFor="let prod of products">{{prod.name}}</div></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">products:Array<any> = [];</div><div class="line">dataSource:Observable<any>;</div><div class="line"></div><div class="line">constructor(private http:Http){</div><div class="line"> this.dataSource = this.http.get('/products')</div><div class="line"> //由于返回的数据格式是Response,过需要转成JSON</div><div class="line"> .map((res)=>res.json())</div><div class="line">};</div><div class="line"></div><div class="line">ngOnInit():void{</div><div class="line"> this.dataSource.subscript(</div><div class="line"> (data)=> this.products = data;</div><div class="line"> )</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>http请求的发送并不是由get方法触发的,而是subscribe;</li>
<li>get方法只是定义了一个http请求,请求的发送是通过订阅完成的;</li>
</ul>
<hr>
<h4 id="异步管道订阅"><a href="#异步管道订阅" class="headerlink" title="异步管道订阅"></a>异步管道订阅</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><div *ngFor="let prod of products | async">{{prod.name}}</div></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">products:Observable<any> = [];</div><div class="line"></div><div class="line">constructor(private http:Http){</div><div class="line"> this.products = this.http.get('/paoducts')</div><div class="line"> .map((res)=>res.json());</div><div class="line">}</div></pre></td></tr></table></figure>
<hr>
<h4 id="添加Headers"><a href="#添加Headers" class="headerlink" title="添加Headers"></a>添加Headers</h4><p>在定义https请求时,需要添加headers的时候,如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">constructor(private http:Http){</div><div class="line"> let myHeaders:Headers = new Headers();</div><div class="line"> myHeaders.append("Autor","tuluffy");</div><div class="line"> </div><div class="line"> this.products = this.http.get('/products',{headers:myHeaders})</div><div class="line"> .map((res)=>res.json());</div><div class="line">}</div></pre></td></tr></table></figure></p>
<h4 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h4><p>有些时候Angular启动的端口地址和服务器端口地址不一致,导致所有的http请求失败。我们需要做端口转发。</p>
<ul>
<li>新建转发配置文件,proxy.conf.json:<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> "/api":{</div><div class="line"> "target":"http://localhost:8080"</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>即:将以”/api”开头的请求地址转发到”<a href="http://localhost:8080" target="_blank" rel="external">http://localhost:8080</a>“</p>
<ul>
<li><p>修改package.json的start项</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">start:"ng serve --proxy-config proxy.conf.json"</div></pre></td></tr></table></figure>
</li>
<li><p>修改请求的地址</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">this.http.get('/products').map((res)=>res.json())</div><div class="line">改为</div><div class="line">this.http.get('/api/products').map((res)=>res.json())</div></pre></td></tr></table></figure>
</li>
</ul>
]]></content>
<summary type="html">
<p>Angular的http服务返回的是Observable(可观察数据流),通过订阅来获取可用数据。</p>
<p>订阅方式有:手动订阅(subscript)、异步管道订阅(async)</p>
<h4 id="手工订阅"><a href="#手工订阅" class="hea
</summary>
</entry>
<entry>
<title>Angular 2(七): 生命周期钩子</title>
<link href="https://github.com/tuluffy/2017/07/26/lifecycle/"/>
<id>https://github.com/tuluffy/2017/07/26/lifecycle/</id>
<published>2017-07-26T06:40:01.000Z</published>
<updated>2017-07-26T06:40:01.000Z</updated>
<content type="html"><![CDATA[<h3 id="钩子的调用顺序:"><a href="#钩子的调用顺序:" class="headerlink" title="钩子的调用顺序:"></a>钩子的调用顺序:</h3><p>consttructor -> ngOnChanges -> ngOnInit -> ngDoCheck -></p>
<p>ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit -></p>
<p>ngAfterViewChecked -> ngOnDestroy</p>
<h4 id="ngOnchanges"><a href="#ngOnchanges" class="headerlink" title="ngOnchanges"></a>ngOnchanges</h4><ul>
<li>当父组件初始化或者修改子组件的输入属性时调用;</li>
<li>如果一个组件没有输入属性,那么永远不会调用该钩子;</li>
<li>首次调用一定在ngOnInit之前;</li>
<li>可以被多次调用;<h5 id="可变对象和不可变对象"><a href="#可变对象和不可变对象" class="headerlink" title="可变对象和不可变对象"></a><strong>可变对象和不可变对象</strong></h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"> let val = 'hello';</div><div class="line"> val = 'hello world';</div><div class="line">`</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li>‘hello’在内存中被创建后赋值给val;</li>
<li>‘hello world’在内存中被创建后赋值给val;</li>
</ul>
<p>无论val如何变化,’hello’在内存中的地址始终保持不变。字符串是不可变对象。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">let user = { name:'roy' };</div><div class="line">user.name = 'joy';</div></pre></td></tr></table></figure>
<ul>
<li>在内存中创建了user,name属性指向’roy’所在的地址;</li>
<li>在内存中创建了’joy’,地址赋值给了user的属性name;</li>
<li>name发生了变化,但是user的地址始终不变;也就是说由于属性的改变,user(对象)是可变对象;</li>
</ul>
<h4 id="ngOnChanges触发机制"><a href="#ngOnChanges触发机制" class="headerlink" title="ngOnChanges触发机制"></a>ngOnChanges触发机制</h4><h5 id="父组件"><a href="#父组件" class="headerlink" title="父组件"></a>父组件</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div></pre></td><td class="code"><pre><div class="line"><div>我是父组件</div></div><div class="line"><div></div><div class="line"> <span>问候语</span></div><div class="line"> <input type="text" [(ngModel)]='hello'/></div><div class="line"></div></div><div class="line"><div></div><div class="line"> <span>名字</span></div><div class="line"> <input type="text" [(ngModel)]='user.name'></div><div class="line"></div></div><div class="line"></div><div class="line"><app-child [childHello]='hello' [childUser]='user'></app-child></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">hello:string;</div><div class="line">user:{name:string} = { name: '' };</div></pre></td></tr></table></figure>
<h5 id="子组件"><a href="#子组件" class="headerlink" title="子组件"></a>子组件</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line"><div>{{childHello}}</div></div><div class="line"><div>{{childUser.name}}</div></div><div class="line"><input type="text" [(ngModel)]="message"/></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">@Input() childHello:string;</div><div class="line">@input() childUser:{name:string};</div><div class="line"></div><div class="line">message:string;</div><div class="line"></div><div class="line">① ngOnChanges(changes:SimpleChanges):void{</div><div class="line"> console.log(changes);</div><div class="line">}</div></pre></td></tr></table></figure>
<p>以上代码结果表现为:</p>
<ul>
<li>当输入问候语hello时,①被触发。原因:由于字符串是不可变对象,然后输入后却发生了变化,故调用ngOnChanges;</li>
<li>修改名字name时,①不触发。原因:由于修改的是可变对象(user的属性虽然变化了,但是user在内存中的地址依然没变),故不会触发ngOnChanges;</li>
<li>当修改message时,①不处罚。原因:ngOnChanges钩子只针对输入属性,message为非输入属性;</li>
</ul>
<p>虽然修改可变对象不会触发ngOnChanges钩子,但是子组件上的值已然发生了变化。这是由于Angular的变更检测机制仍然不活了组件中每个对象的属性的变化。</p>
<hr>
<h4 id="ngDoCheck"><a href="#ngDoCheck" class="headerlink" title="ngDoCheck"></a>ngDoCheck</h4><h5 id="在这里,需要先重点说一下Angular的变更检测机制"><a href="#在这里,需要先重点说一下Angular的变更检测机制" class="headerlink" title="在这里,需要先重点说一下Angular的变更检测机制"></a>在这里,需要先重点说一下Angular的变更检测机制</h5><ul>
<li>在Angular1.x中,任何原生事件都不会触发脏检查,必须使用NG事件才有效。如果使用了原生事件,你需要指定$apply()和$digest()来告诉Angular使用变更检测去处理它。</li>
<li><p>在Angular2中,变更检测机制是由zone.js提供的,保证组件的属性的变化和页面的变化是同步的。</p>
<ul>
<li>浏览器中发生的任何事件都会触发变更检测,如:点击事件、输入数据;</li>
<li>可以随意使用任何原生事件;</li>
</ul>
</li>
</ul>
<p>变更检测机制仅仅是将组件属性的改变反应到模块上,它并不会去改变组件属性的值。</p>
<h5 id="变更检测"><a href="#变更检测" class="headerlink" title="变更检测"></a>变更检测</h5><ul>
<li>每一个组件生成属于他们的变更检测器。当属性发生变化时,变更检测器指定的变更检测机制(default和Onush)就会响应,并判断是否需要更新模块;</li>
<li>变更检测策略:<ul>
<li>Default策略:采用Default策略的组件,无论组件树的哪个地方发生变化,都会被检测;检测顺序:根组件->子组件->孙组件;</li>
<li>Onpush策略:只有当组件的输入属性发生变化,变更检测机制才会检测该组件及其子组件; </li>
</ul>
</li>
</ul>
<h5 id="对可变对象的检测:ngDoCheck"><a href="#对可变对象的检测:ngDoCheck" class="headerlink" title="对可变对象的检测:ngDoCheck"></a>对可变对象的检测:ngDoCheck</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">ngDoCheck():void{</div><div class="line"> if(this.user.name != this.oldname){</div><div class="line"> //do something</div><div class="line"> console.log(this.user.nane); //新值</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>组件中只要有事件发生,ngDoCheck就会被调用①,比如:在两个文本框之间切换;</li>
<li>由于①的原因,ngOnCheck非常容易被调用,使用时需要小心。对于ngOnCheck的实现要非常高效和轻量,否则容易因其性能问题;</li>
<li>在Default策略下,每次变更检测,组件树中所有带check后缀的钩子都会被调用;</li>
</ul>
<hr>
<h4 id="view钩子"><a href="#view钩子" class="headerlink" title="view钩子"></a>view钩子</h4><ul>
<li><p>子组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">getVal(val:string):void{</div><div class="line"> console.log(val);</div><div class="line">}</div><div class="line"></div><div class="line">①ngAfterViewInit():void{}</div><div class="line">②ngAfterViewChecked():void{}</div></pre></td></tr></table></figure>
</li>
<li><p>父组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><div>我是父组件</div></div><div class="line"><app-child #child1></app-child></div><div class="line"><app-child #child2></app-child></div><div class="line"><button (click)="child2.getVal('joy')"></button></div></pre></td></tr></table></figure>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">@ViewChild('child1') child1:ChildComponent;</div><div class="line"> </div><div class="line">ngOnInit():void{</div><div class="line"> this.child1.getVal('hahh');</div><div class="line">}</div><div class="line"> </div><div class="line">③ngAfterViewInit():void{}</div><div class="line">④ngAfterViewChecked():void{}</div></pre></td></tr></table></figure>
<p>钩子调用顺序:①->②->③->④</p>
<ul>
<li>很明显,子组件必须在父组件之前组装完毕,init方法只会被调用一次;</li>
<li>在变更检测周期中禁止修改属性,如果必须修改需要在子线程中操作;<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">ngAfterViewInit():void{</div><div class="line"> this.val = "hhahh"; //严重错误</div><div class="line"> </div><div class="line"> //解决方案</div><div class="line"> setTimeout(()=>{</div><div class="line"> this.val = "hahha";</div><div class="line"> },0)</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h4 id="ngContent指令"><a href="#ngContent指令" class="headerlink" title="ngContent指令"></a>ngContent指令</h4><ul>
<li>一般写法</li>
</ul>
<p>子组件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line"><div></div><div class="line"> <div>我是子组件</div></div><div class="line"> <ng-content></ng-content> //投影点</div><div class="line"></div></div></pre></td></tr></table></figure></p>
<p>父组件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><div></div><div class="line"> <div>我是父组件</div></div><div class="line"> <app-child></div><div class="line"> <div>这里面是投影内容</div></div><div class="line"> <div>{{title}}</div> //虽然是投影在子组件中的内容,但是只能在父组件中操作</div><div class="line"> </app-child> </div><div class="line"></div></div></pre></td></tr></table></figure></p>
<ul>
<li>多个投影的写法<br>父组件<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><div></div><div class="line"> <div>父组件</div></div><div class="line"> <app-child></div><div class="line"> <div class="firstPart">这是第一块内容</div></div><div class="line"> <div class="secondPart">这是第二块内容</div></div><div class="line"> </app-child></div><div class="line"></div></div></pre></td></tr></table></figure>
</li>
</ul>
<p>子组件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><div></div><div class="line"> <div>子组件</div></div><div class="line"> <ng-content select=".firstPart"></ng-content></div><div class="line"> <ng-content select=".secondPart"></ng-content></div><div class="line"></div></div></pre></td></tr></table></figure></p>
<hr>
<h4 id="ngAfterContentInit、ngAfterContentChecked"><a href="#ngAfterContentInit、ngAfterContentChecked" class="headerlink" title="ngAfterContentInit、ngAfterContentChecked"></a>ngAfterContentInit、ngAfterContentChecked</h4><ul>
<li><p>在投影内容组装完成之后调用、检测之后调用;</p>
</li>
<li><p>执行顺序:ngAfterContentInit -> ngAfterContentChecked -> ngAfterContentInit -> ngAfterContentChecked -> ngAfterViewInit</p>
</li>
<li><p>与ngAfterView的钩子不同,在ngAfterContent的钩子中可以改变属性的值</p>
</li>
</ul>
<hr>
<h4 id="ngOnDestory"><a href="#ngOnDestory" class="headerlink" title="ngOnDestory"></a>ngOnDestory</h4><ul>
<li>当组件销毁的时候调用该钩子(配合路由使用);</li>
<li>往往在该钩子中处理“反订阅一个流”、“清除定时器”等操作;</li>
</ul>
<hr>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul>
<li><p>组件初始化</p>
<p> ①constructor</p>
<p> ②ngOnChanges</p>
<p> ③ngOnInit</p>
<p> ④ngDoCheck</p>
<p> ⑤ngAfterContentInit</p>
<p> ⑥ngAfterContentChecked</p>
<p> ⑦ngAfterViewInit</p>
<p> ⑧ngAfterViewChecked</p>
<p> ⑨ngOnDestory</p>
</li>
<li><p>组件销毁 </p>
<p> ⑨ngOnDestory</p>
</li>
<li><p>变更检测</p>
<p> ②ngOnChanges</p>
<p> ④ngDoCheck</p>
<p> ⑥ngAfterContentChecked</p>
<p> ⑧ngAfterViewChecked</p>
</li>
</ul>
<h4 id="每一个组件都会经历三个阶段:初始化、变更检测、销毁"><a href="#每一个组件都会经历三个阶段:初始化、变更检测、销毁" class="headerlink" title="每一个组件都会经历三个阶段:初始化、变更检测、销毁"></a>每一个组件都会经历三个阶段:初始化、变更检测、销毁</h4><ul>
<li><p>当通过路由激活一个组件(按先后顺序):</p>
<p> 组件初始工作:</p>
<ul>
<li><p>启动constructor,提供所需实例化的对象</p>
</li>
<li><p>如果有输入属性,启动ngOnChanges检测输入属性的变更</p>
</li>
<li><p>启动ngOnInit,初始化一般数据</p>
</li>
<li><p>启动ngDoCheck,进行一次变更检测</p>
</li>
</ul>
<p>开始组装组件:</p>
<ul>
<li><p>当组件中的投影内容被组装时,调用ngAfterContentInit</p>
</li>
<li><p>启动ngAfterContentChecked,对投影内容检测</p>
</li>
<li><p>当整个组件被组装时,调用ngAfterViewInit</p>
</li>
<li><p>启动ngAfterViewChecked,对整个组件检测</p>
<p>组件变更:</p>
</li>
<li><p>当有事件发生(用户操作),启动ngDoCheck进行变更检测</p>
</li>
<li><p>处理变更,如果需要更新组件,启动ngAfterContentChecked、ngAfterViewChecked;如果输入属性发生变化,启动ngOnChanges</p>
</li>
<li><p>路由事件发生,启动ngOnDestory销毁组建,从头开始初始化一个组件;</p>
</li>
</ul>
</li>
</ul>
]]></content>
<summary type="html">
<h3 id="钩子的调用顺序:"><a href="#钩子的调用顺序:" class="headerlink" title="钩子的调用顺序:"></a>钩子的调用顺序:</h3><p>consttructor -&gt; ngOnChanges -&gt; ngOnInit
</summary>
</entry>
<entry>
<title>Angular 2(六): 输入属性、输出属性</title>
<link href="https://github.com/tuluffy/2017/07/25/output/"/>
<id>https://github.com/tuluffy/2017/07/25/output/</id>
<published>2017-07-25T06:31:28.000Z</published>
<updated>2017-07-25T06:31:28.000Z</updated>
<content type="html"><![CDATA[<h3 id="输入属性"><a href="#输入属性" class="headerlink" title="输入属性"></a>输入属性</h3><h4 id="父组件单向向子组件中传值"><a href="#父组件单向向子组件中传值" class="headerlink" title="父组件单向向子组件中传值"></a>父组件单向向子组件中传值</h4><ul>
<li><p>父组件:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><div>我是父组件</div></div><div class="line"><app-child [myVal]="val"></app-child></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">val: string = '这是在父组件的控制器中赋值!';</div></pre></td></tr></table></figure>
</li>
<li><p>子组件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><div>{{myVal}}</div></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">//在子组件中将“myVal”声明为输入属性</div><div class="line">//至此,父组件中的值就能直接传递给"myVal"了</div><div class="line">@Input() myVal;</div></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="输出属性"><a href="#输出属性" class="headerlink" title="输出属性"></a>输出属性</h3><h4 id="数据从子组件中发射,在父组件中捕获"><a href="#数据从子组件中发射,在父组件中捕获" class="headerlink" title="数据从子组件中发射,在父组件中捕获"></a>数据从子组件中发射,在父组件中捕获</h4><ul>
<li><p>子组件:对外发射数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">① @Output() </div><div class="line">② outObjName: EventEmitter<Product> = new EventEmitter();</div><div class="line"></div><div class="line">constructor(){</div><div class="line">③ let prod: Product = new Product("joy",13);</div><div class="line">④ this.outObjName.emit(prod);</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li>①②表示声明一个输出属性(也可以说成输出对象),该属性具有发射数据的能力;</li>
<li>②中,需要为声明的属性指明一个泛型,EventEmitter<泛型>。该泛型即是:对外发射的数据的类型;</li>
<li>③生成一个符合规则的数据;</li>
<li>④使用输出属性将数据发射出去(发射到父组件中);</li>
</ul>
</li>
</ul>
<ul>
<li>父组件:接收来自于子组件的数据 <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><div>我是父组件</div></div><div class="line">④ <app-child (outObjName)="getDataFromChild($event)"></app-child></div></pre></td></tr></table></figure>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">① prodInParent : Product = new Product();</div><div class="line"></div><div class="line">② getDataFromChild(ev:Product){</div><div class="line">③ this.prodInParent = ev;</div><div class="line">}</div></pre></td></tr></table></figure>
<p> 在Angular中,捕获子组件中发射的事件,和捕获原生的DOM事件是一样的操作。</p>
<ul>
<li>①中新建了了一个Product的实例,为接收数据做准备;</li>
<li>②自定义函数,捕获从子组件中发射出来的指定类型的数据;</li>
<li>③使用捕获到的数据</li>
<li>④对子组件中发射事件进行监听,一旦捕获到,立即响应指定的操作(getDataFromChild)</li>
</ul>
<h3 id="补充说明:"><a href="#补充说明:" class="headerlink" title="补充说明:"></a>补充说明:</h3><ul>
<li>一般情况下,父组件中“捕获的事件名称”和子组件中“输出属性的名称”保持一致;</li>
<li>如果需要给输出属性指定别名,可以:@Output(‘otherName’)。这时,在父组件中④的位置outObjName需要与otherName相同;</li>
</ul>
<h3 id="中间人模式:"><a href="#中间人模式:" class="headerlink" title="中间人模式:"></a>中间人模式:</h3><ul>
<li>简单来说,使用一个公共的父组件来连通两个不相关的组件,使之间的数据和事件响应在一定程度上得到关联;</li>
<li>使用中间人模式既实现既定功能,也实现了组件之间的解耦; </li>
</ul>
]]></content>
<summary type="html">
<h3 id="输入属性"><a href="#输入属性" class="headerlink" title="输入属性"></a>输入属性</h3><h4 id="父组件单向向子组件中传值"><a href="#父组件单向向子组件中传值" class="headerlink"
</summary>
</entry>
<entry>
<title>Angular 2(五): 注入器、数据绑定、管道</title>
<link href="https://github.com/tuluffy/2017/07/24/databind/"/>
<id>https://github.com/tuluffy/2017/07/24/databind/</id>
<published>2017-07-24T09:23:46.000Z</published>
<updated>2017-07-24T09:23:46.000Z</updated>
<content type="html"><![CDATA[<h3 id="注入器"><a href="#注入器" class="headerlink" title="注入器"></a>注入器</h3><h4 id="1-注入器及其层级关系"><a href="#1-注入器及其层级关系" class="headerlink" title="1.注入器及其层级关系"></a>1.注入器及其层级关系</h4><ul>
<li><p>第一步:Angular在应用启动时,会生成一个应用级的注入器,将主模块和引用模块中的提供器(provide)全部注入到其中;</p>
<ul>
<li>NgModule中的providers内声明的提供器</li>
<li>imports中的模块(BrowserModule、HttpModule)依赖的提供器</li>
</ul>
</li>
<li><p>第二步:Angular创建启动模块指定的主组件(AppComponent),同时应用级的注入器会为主组件创建一个组件级的注入器。</p>
<p>并将主组件中声明的提供器注入到组件级的注入其中;</p>
</li>
<li><p>第三步:在主组件中的子组件被创建时,主组件的注入器会为被激活的子组件创建一个组件级的注入器;</p>
<p> 并将子组件中的提供器注入其中;</p>
<h4 id="以此类推,最终形成一套注入器层级关系。"><a href="#以此类推,最终形成一套注入器层级关系。" class="headerlink" title="以此类推,最终形成一套注入器层级关系。"></a>以此类推,最终形成一套注入器层级关系。</h4><h4 id="2-注入器的使用"><a href="#2-注入器的使用" class="headerlink" title="2.注入器的使用"></a>2.注入器的使用</h4></li>
<li><p>Angular只提供在构造函数中注入的方式来创建服务;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">constructor(private service:Service){</div><div class="line"> //this.service.methodName();</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>除了常用的在构造函数的参数直接声明服务以外,还可以手动调用注入器获取需要的服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">constructor(private injector:Injector){</div><div class="line"> this.service = injector.get("Service");</div><div class="line"> this.service.methodName();</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h3 id="数据绑定"><a href="#数据绑定" class="headerlink" title="数据绑定"></a>数据绑定</h3><h4 id="Angular才用的是DOM属性绑定的模式来完成数据绑定。"><a href="#Angular才用的是DOM属性绑定的模式来完成数据绑定。" class="headerlink" title="Angular才用的是DOM属性绑定的模式来完成数据绑定。"></a>Angular才用的是DOM属性绑定的模式来完成数据绑定。</h4><h4 id="1-DOM属性绑定流程"><a href="#1-DOM属性绑定流程" class="headerlink" title="1.DOM属性绑定流程"></a>1.DOM属性绑定流程</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><input type="text" value='1' (input)="console($event)"/></div></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">console(ev):any{</div><div class="line"> ① console.log(ev.target.value);</div><div class="line"> ② console.log(ev.target.getAttribute('value'));</div><div class="line">}</div></pre></td></tr></table></figure>
<p>在input事件发生的时候,在控制台中可以看到①打印的值与文本框保持一致,而②始终是默认的value值;</p>
<p>这是因为HTML属性指向的是初始值,而DOM属性指向的是当前值,且HTML属性不可变;</p>
<ul>
<li>DOM属性发生变化时的流程<ol>
<li>(组件)input中的值发生变化</li>
<li>DOM属性发生变化,HTML属性不变</li>
<li>浏览器保持DOM属性和UI同步</li>
<li>value渲染到页面</li>
</ol>
</li>
</ul>
<h4 id="2-HTML属性绑定流程"><a href="#2-HTML属性绑定流程" class="headerlink" title="2.HTML属性绑定流程"></a>2.HTML属性绑定流程</h4><ul>
<li>HTML属性发生变化时的流程 <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line">① <div [colspan]="{{1+1}}"></div></div><div class="line">② <div [attr.colspan]="val"></div></div></pre></td></tr></table></figure>
</li>
</ul>
<p>由于Angular使用的是DOM属性绑定,而DOM属性中没有colspan,故①中的写法会报错;</p>
<ul>
<li><p>DOM属性发生变化时的流程 </p>
<ol>
<li>(控制器)数据发生变化</li>
<li>更新HTML元素,不更新DOM元素</li>
<li>(浏览器同步HTML元素和DOM对象)DOM节点发生变化,造成DOM对象的属性发生变化</li>
<li>浏览器同步DOM属性和UI</li>
<li>渲染页面</li>
</ol>
</li>
</ul>
<hr>
<h3 id="管道"><a href="#管道" class="headerlink" title="管道"></a>管道</h3><p>cli命令创建管道:ng g pipe pipeName</p>
<h4 id="1-管道的标准形式"><a href="#1-管道的标准形式" class="headerlink" title="1.管道的标准形式"></a>1.管道的标准形式</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">import { Pipe,PipeTransform } from '@angular/core';</div><div class="line"></div><div class="line">@Pipe({ name: "timeFilter" })</div><div class="line"></div><div class="line">export class TimeFilter implements PipeTransform{</div><div class="line"> transform(value:any,argu:any):any{</div><div class="line"> return null;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<h4 id="2-管道-是数据扩大指定的倍数"><a href="#2-管道-是数据扩大指定的倍数" class="headerlink" title="2.管道:是数据扩大指定的倍数"></a>2.管道:是数据扩大指定的倍数</h4><ul>
<li><p>extraMultiple.ts</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">transform(value:number,multiple?:number):number{</div><div class="line"> if(!multiple){ multiple = 1; }</div><div class="line"> return value * multiple;</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>app.component.html</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><p>{{ val | extraMultiple: '3' }}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>如果有多个过滤参数:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><p>{{ val | pipeName: 'argu1' : 'agru2' }}</p></div></pre></td></tr></table></figure></p>
<hr>
<h3 id="其他:"><a href="#其他:" class="headerlink" title="其他:"></a>其他:</h3><ul>
<li>少量HTML属性和DOM属性有一一对应的关系,如“id”;</li>
<li>有些HTML属性没有对应的DOM属性,如“colspan”;</li>
<li>有些DOM属性没有对应的HTML属性,如“textContent”;</li>
<li>就算属性名字相同,DOM属性和HTML属性不是一样的东西; </li>
<li>HTML属性指定初始值(不可变),DOM属性指向当前值(可变);</li>
</ul>
]]></content>
<summary type="html">
<h3 id="注入器"><a href="#注入器" class="headerlink" title="注入器"></a>注入器</h3><h4 id="1-注入器及其层级关系"><a href="#1-注入器及其层级关系" class="headerlink" title=
</summary>
</entry>
<entry>
<title>Angular 2(四): 依赖注入和控制反转</title>
<link href="https://github.com/tuluffy/2017/07/24/diIoc/"/>
<id>https://github.com/tuluffy/2017/07/24/diIoc/</id>
<published>2017-07-24T03:20:43.000Z</published>
<updated>2017-07-24T03:20:43.000Z</updated>
<content type="html"><![CDATA[<h3 id="基础概念"><a href="#基础概念" class="headerlink" title="基础概念"></a>基础概念</h3><h4 id="依赖注入和控制反转"><a href="#依赖注入和控制反转" class="headerlink" title="依赖注入和控制反转"></a>依赖注入和控制反转</h4><ul>
<li>A依赖于B,A不需要在代码内部直接创建B的实例对象,而是由外部提供(B的实例对象); </li>
<li>将依赖的控制权从代码的内部转移到代码的外部;</li>
</ul>
<p>依赖注入和控制反转是一体两面,依赖注入是目的,控制反转是手段,终究实现代码的松耦合。</p>
<h4 id="token"><a href="#token" class="headerlink" title="token"></a>token</h4><ul>
<li>示例代码<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">@NgModule({</div><div class="line"> ①providers: [ ProdService ]</div><div class="line"> </div><div class="line"> ②providers: [{</div><div class="line"> provide: ProdService,</div><div class="line"> useClass: ProdService,</div><div class="line"> }]</div><div class="line">})</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li>token在Angular中代表一个被注入的对象的类型,由provide决定;</li>
<li>如:示例代码中,注册的Token的类型为ProdService;</li>
<li>当有组件或者指令声明(在其构造函数中)需要一个类型为ProdService的token时,注入器就会实例化一个ProdService对象(由useClass决定实例化哪个),并将其注入到组件中;</li>
<li>在组件中,通过构造函数获得该对象<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">constructor(private prodService:ProdService){</div><div class="line"> //prodService</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="服务的三种使用形式:useClass、useFactory、useValue"><a href="#服务的三种使用形式:useClass、useFactory、useValue" class="headerlink" title="服务的三种使用形式:useClass、useFactory、useValue"></a>服务的三种使用形式:useClass、useFactory、useValue</h3><h4 id="Injectable-,表示可以在该类中注入其他服务,建议所有的服务都加上该声明;"><a href="#Injectable-,表示可以在该类中注入其他服务,建议所有的服务都加上该声明;" class="headerlink" title="@Injectable(),表示可以在该类中注入其他服务,建议所有的服务都加上该声明;"></a>@Injectable(),表示可以在该类中注入其他服务,建议所有的服务都加上该声明;</h4><h4 id="useClass"><a href="#useClass" class="headerlink" title="useClass"></a>useClass</h4><ul>
<li>服务建议放在模块(即:app.module.ts的providers中)中,使之成为全局共享;</li>
<li>如果将服务放在组件中,那么它只能在局部使用(组件及其子组件)。对于同名的token请求,组件中的服务类将覆盖模块中的服务类;</li>
</ul>
<p>1.productService.ts</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">@Injectable()</div><div class="line">export class ProductService{</div><div class="line"> //do something</div><div class="line"> getProduct():Product{</div><div class="line"> return new Product(...)</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<p>2.anthorProductService.ts<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">@Injectable()</div><div class="line">export class AnthorProductService implements ProductService{</div><div class="line"> //do something</div><div class="line"> getProduct():Product{</div><div class="line"> return new Product(...);</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>3.app.module.ts<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">@NgModule({</div><div class="line"> providers:[ ProductService ]</div><div class="line">})</div></pre></td></tr></table></figure></p>
<p>4.product.component.html</p>
<p>使用在模块中声明的服务<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">@Component({</div><div class="line"> ...,</div><div class="line">})</div><div class="line">export class ProductComponent implements OnInit{</div><div class="line"> constructor(private ps:ProductService){}</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p>使用在组件中的服务<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">@Component({</div><div class="line"> ...,</div><div class="line"> providers:[</div><div class="line"> {</div><div class="line"> provide:ProductService,</div><div class="line"> useClass:AnthorProductService</div><div class="line"> }</div><div class="line"> ]</div><div class="line"> })</div><div class="line"> export class ProductComponent implements OnInit{</div><div class="line"> //声明使用ProductService类型的token,会使用AnthorProductService类创建实例</div><div class="line"> constructor(private ps:ProductService){}</div><div class="line"> }</div></pre></td></tr></table></figure></p>
<hr>
<h3 id="提供器之-useFactory"><a href="#提供器之-useFactory" class="headerlink" title="提供器之 useFactory"></a>提供器之 useFactory</h3><p>在提供服务时,可能要根据不同的状态去初始化不同的服务实例,这时需要使用useFactory提供器来完成。</p>
<p>通过随机数模拟开发/生产状态来实例化不同的服务类:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">providers:[</div><div class="line"> {</div><div class="line"> provide: ProductService,</div><div class="line"> useFactory:()=>{</div><div class="line"> ① let log = new LogService();</div><div class="line"> let dev = Math.random() > 0.5;</div><div class="line"> </div><div class="line"> if(dev){</div><div class="line"> return new ProductService(log);</div><div class="line"> }</div><div class="line"> else {</div><div class="line"> return new AnthorProductService(log);</div><div class="line"> }</div><div class="line"> }</div><div class="line"> },</div><div class="line"> LogService </div><div class="line">],</div></pre></td></tr></table></figure></p>
<ul>
<li>以上,我们就完成了模拟开发/生产环境来提供不同的服务实例,而在组件内部使用的时候根本不知道我们提供的是什么。这也就实现了服务和组件的初步解耦。</li>
<li>同时,如果你细心一点,在使用的过程中会发现整个应用内部ProductService类型的token对应的服务实例是同一个。由此可以说:工厂方法创建的对象是单例对象,在该对象被初次创建之后,整个应用内部都是使用同一个。</li>
<li>但是,轻而易举地发现在useFactory的方法内部出现了①这样的写法,LogService和ProductService强耦合。我们需要解决这个问题,使用提供器的第三个参数配置deps(数组):</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> provide: ProductService,</div><div class="line"> useFactory:(log:LogService)=>{</div><div class="line"> let dev = Math.random() > 0.5;</div><div class="line"> </div><div class="line"> if(dev){</div><div class="line"> return new ProductService(log);</div><div class="line"> }</div><div class="line"> else {</div><div class="line"> return new AnthorProductService(log);</div><div class="line"> }</div><div class="line"> },</div><div class="line"> deps:[ LogService ]</div><div class="line">},</div><div class="line">LogService</div></pre></td></tr></table></figure>
<ul>
<li>上面代码实现了服务(ProductService)和服务(LogService)之间的解耦。ProductService将使用外部的LogService来注入工厂方法内部,从而创建实例。</li>
</ul>
<hr>
<h3 id="提供器之-useValue"><a href="#提供器之-useValue" class="headerlink" title="提供器之 useValue"></a>提供器之 useValue</h3><p>该提供器方法常常结合useFactory使用<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div></pre></td><td class="code"><pre><div class="line">providers:[</div><div class="line"> {</div><div class="line"> provide...,</div><div class="line"> useFactory:(log:LogService,isDev)=>{</div><div class="line"> //do something</div><div class="line"> },</div><div class="line"> deps:[ LogService,"IS_DEV" ]</div><div class="line"> },</div><div class="line"> {</div><div class="line"> provide:"IS_DEV",</div><div class="line"> useValue:false</div><div class="line"> }</div><div class="line">]</div></pre></td></tr></table></figure></p>
<ul>
<li>useValue的值也可以使用对象:<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> provide:"APP_CONFIG",</div><div class="line"> useValue:{ isDev:false }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h4 id="Angular在启动的时候,在创建服务的过程中会对每一个服务的依赖进行实例化并注入到当前服务中,如此一层一层递进直至结束。于是"><a href="#Angular在启动的时候,在创建服务的过程中会对每一个服务的依赖进行实例化并注入到当前服务中,如此一层一层递进直至结束。于是" class="headerlink" title="Angular在启动的时候,在创建服务的过程中会对每一个服务的依赖进行实例化并注入到当前服务中,如此一层一层递进直至结束。于是"></a>Angular在启动的时候,在创建服务的过程中会对每一个服务的依赖进行实例化并注入到当前服务中,如此一层一层递进直至结束。于是</h4><ul>
<li>每一个服务都是独立的,服务与服务之间不存在耦合。</li>
<li>每一个组件在申请使用服务的时候,并不知道服务是如何构建的,组件与服务之间不存在耦合。</li>
</ul>
<p>以上两点就是Angular实现“依赖注入”和“控制反转”的核心。 </p>
]]></content>
<summary type="html">
<h3 id="基础概念"><a href="#基础概念" class="headerlink" title="基础概念"></a>基础概念</h3><h4 id="依赖注入和控制反转"><a href="#依赖注入和控制反转" class="headerlink" title=
</summary>
</entry>
<entry>
<title>Angular 2(三): 子路由和守卫</title>
<link href="https://github.com/tuluffy/2017/07/20/childRouter/"/>
<id>https://github.com/tuluffy/2017/07/20/childRouter/</id>
<published>2017-07-20T02:33:12.000Z</published>
<updated>2017-07-20T02:33:12.000Z</updated>
<content type="html"><![CDATA[<h2 id="子路由"><a href="#子路由" class="headerlink" title="子路由"></a>子路由</h2><p> 子路由相对于根路由的概念而来,示例:children:数组,配置路由相关信息</p>
<p> 路由配置:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> path:'product',</div><div class="line"> component:ProductComponent,</div><div class="line"> children:[ //关键字</div><div class="line"> {</div><div class="line"> path:'',</div><div class="line"> component:ProductDescComponent //商品简介组件</div><div class="line"> },</div><div class="line"> {</div><div class="line"> path:'seller/:id',</div><div class="line"> component:SellerDetailComponent //具体商品信息组件</div><div class="line"> }</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure></p>
<p> 父组件:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">注意[routerLink] = "['./']",路径中加"."指明是匹配子路由</div><div class="line"> <a [routerLink] = "['./']">商品简介</a></div><div class="line"> <a [routerLink] = "['./seller/3']">商品信息</a></div><div class="line"> <router-outlet></router-outlet> //供子组件使用的路由插座</div></pre></td></tr></table></figure></p>
<hr>
<h2 id="辅助路由"><a href="#辅助路由" class="headerlink" title="辅助路由"></a>辅助路由</h2><p> 概览:辅助路由可以有多个,根据“name”字段来匹配</p>
<ul>
<li>路由配置<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> path:'xxx',</div><div class="line"> component:XComponent,</div><div class="line"> outlet:"aux", //匹配路由名字,确定放在哪个辅助路由上</div><div class="line">},</div><div class="line">{</div><div class="line"> path:'yyy',</div><div class="line"> component:YComponent,</div><div class="line"> outlet:"aux",</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li>父组件写法,假设是在app.component.html中<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><a [routerLink]="['/home',{ outlets:{ aux:"xxx" } }]">GOTO XXX</a></div><div class="line"><a [routerLink]="['/home',{ outlets:{ aux:"yyy" } }]">GOTO YYY</a></div><div class="line"></div><div class="line"><router-outlet></router-outlet> //主路由</div><div class="line"><router-outlet name="aux"></router-outlet> //辅助路由</div><div class="line"><router-outlet name="other"></router-outlet> //可以有多个辅助路由</div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h2 id="路由守卫"><a href="#路由守卫" class="headerlink" title="路由守卫"></a>路由守卫</h2><h3 id="路由守卫的意义在于,路由事件发生后,是否允许默认操作(比如,跳转到指定的页面)"><a href="#路由守卫的意义在于,路由事件发生后,是否允许默认操作(比如,跳转到指定的页面)" class="headerlink" title="路由守卫的意义在于,路由事件发生后,是否允许默认操作(比如,跳转到指定的页面)"></a>路由守卫的意义在于,路由事件发生后,是否允许默认操作(比如,跳转到指定的页面)</h3><p>如何使用?示例:</p>
<ul>
<li><p>路由文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line">import LoginGuard from "...";</div><div class="line">import TokenGuard from "...";</div><div class="line"></div><div class="line">const routes : Routes = [</div><div class="line"> {</div><div class="line"> path:'product',</div><div class="line"> component:ProductComponent,</div><div class="line"> //路由钩子对象(对应loginGuard.ts中的钩子接口)</div><div class="line"> canActivate:[ //是否可以进入该组件</div><div class="line"> LoginGuard //控制函数(路由钩子函数),只有当所有的函数都返回true时,才可以进入组件</div><div class="line"> TokenGuard</div><div class="line"> ]</div><div class="line"> }</div><div class="line">];</div><div class="line"></div><div class="line">@NgModule({</div><div class="line"> import:[RouterModule.forRoot(routes)],</div><div class="line"> exports:[RouterModule],</div><div class="line"> providers:[ LoginGuard,TokenGuard ]</div><div class="line">})</div></pre></td></tr></table></figure>
</li>
<li><p>守卫文件:loginGuard.ts</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">export class LoginGuard implements CanActivate{</div><div class="line"> CanActivate():boolean{ //接收一个boolean类型的返回值</div><div class="line"> //处理逻辑,比如判断token是否有效</div><div class="line"> //return true; </div><div class="line"> return false;</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p>增加一个CanDeactivate守卫,表示是否可以离开该组件(常用来检查用户填写的信息是否已经保存):</p>
<p> 实现守卫(实现CanDeactivate守卫接口)接口,unSaveGuard.ts文件中<br> 注意事项:</p>
<ul>
<li>该守卫需要接受一个组件作为参数(即保护的组件);</li>
<li>在守卫函数中,需要创建组件的对象(comp),通过该对象获得组件内部的属性判断是否已经保存</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line">import { CanDeactivate } from '...';</div><div class="line"></div><div class="line">export class UnSaveGuard implements CanDeactivate<ProductComponent>{</div><div class="line"> canDeactivate(comp:ProductComponent){</div><div class="line"> //逻辑操作,对组件内部的变量进行验证是否已经保存</div><div class="line"> comp.varibleName; </div><div class="line"> </div><div class="line"> //return true; //是否允许离开</div><div class="line"> return false;</div><div class="line"></div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
<ul>
<li><p>将守卫加入到路由配置中</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> path: 'product',</div><div class="line"> component: ProductComponent,</div><div class="line"> canActivate:[ LoginGuard,TokenGuard ],</div><div class="line"> canDeactivate:[ UnSaveGuard ] //只有一系列函数都return true才可以顺利执行路由操作</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>在NgModule中配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">providers: [ loginGuard,TokenGuard,UnSaveGuard ]</div></pre></td></tr></table></figure>
</li>
</ul>
<hr>
<h2 id="resolve守卫"><a href="#resolve守卫" class="headerlink" title="resolve守卫"></a>resolve守卫</h2><p>该守卫常用在进入下一个组件之前,执行服务获取下一个组件需要用到的数据,并带入组件中。<br>所以该组件需要可以被注入,在写时需要加入@Injectable()标识</p>
<ul>
<li><p>路由配置项改写</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> path:'product',</div><div class="line"> component:ProductComponent,</div><div class="line"> resolve:{</div><div class="line"> prod: ProductResolve //prod是传入组件中的参数集合的对象</div><div class="line"> }</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>写productResolve.ts文件,提供ProductResolve函数</p>
</li>
<li><p>该class需要指定返回的参数的格式,即:<product></product></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">export class ProductResolve implements Resolve<Product>{</div><div class="line"> resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Product>|Promise<Product>|Product {</div><div class="line"> //发起请求,获取数据</div><div class="line"> return data; //将解析好的数据传递到组件内部,之后订阅该字段获取数据</div><div class="line"> }</div><div class="line"></div><div class="line">}</div></pre></td></tr></table></figure>
</li>
<li><p>在组建中取值(采用订阅的方式)</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">constructor(private routeInfo:ActivatedRoute){}</div><div class="line"></div><div class="line">ngOnInit(){</div><div class="line"> this.routeInfo.data.subscribe((data:{prod:Product}) => {</div><div class="line"> this.id = data.prod.id; </div><div class="line"> })</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="本章内容主要通过代码展示,比较粗略。如果发现文档中的错漏,或者涉及到具体问题,可以联系QQ-3265564490-备注:Angular-笔记"><a href="#本章内容主要通过代码展示,比较粗略。如果发现文档中的错漏,或者涉及到具体问题,可以联系QQ-3265564490-备注:Angular-笔记" class="headerlink" title="本章内容主要通过代码展示,比较粗略。如果发现文档中的错漏,或者涉及到具体问题,可以联系QQ:3265564490,备注:Angular 笔记"></a>本章内容主要通过代码展示,比较粗略。如果发现文档中的错漏,或者涉及到具体问题,可以联系QQ:3265564490,备注:Angular 笔记</h3>]]></content>
<summary type="html">
<h2 id="子路由"><a href="#子路由" class="headerlink" title="子路由"></a>子路由</h2><p> 子路由相对于根路由的概念而来,示例:children:数组,配置路由相关信息</p>
<p> 路由配置:<br> <figu
</summary>
</entry>
<entry>
<title>Angular 2(二): 路由</title>
<link href="https://github.com/tuluffy/2017/07/11/router/"/>
<id>https://github.com/tuluffy/2017/07/11/router/</id>
<published>2017-07-11T10:30:07.000Z</published>
<updated>2017-07-11T10:30:07.000Z</updated>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><h4 id="router是Angular-内置模块,可以使用cli-提供的指令来创建包含route-组件的项目"><a href="#router是Angular-内置模块,可以使用cli-提供的指令来创建包含route-组件的项目" class="headerlink" title="router是Angular 内置模块,可以使用cli 提供的指令来创建包含route 组件的项目"></a>router是Angular 内置模块,可以使用cli 提供的指令来创建包含route 组件的项目</h4> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">$ ng new router --routing</div></pre></td></tr></table></figure>
<p> 此时,在app.module.ts 文件中可以看到已经被自动引入到 imports组中。<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">imports: [</div><div class="line"> BrowserModule,</div><div class="line"> AppRoutingModule</div><div class="line"> ],</div></pre></td></tr></table></figure></p>
<hr>
<h2 id="路由组件相关字段含义"><a href="#路由组件相关字段含义" class="headerlink" title="路由组件相关字段含义"></a>路由组件相关字段含义</h2><h3 id="1-Routes,路由的配置项"><a href="#1-Routes,路由的配置项" class="headerlink" title="1. Routes,路由的配置项"></a>1. Routes,路由的配置项</h3><ul>
<li>保存路由信息,即:url和component的对应关系</li>
<li>指定组件展示在哪个路有插座上(<RouterOutLet></RouterOutLet>)</li>
</ul>
<h3 id="2-RouterOutLet,路由插座,即:激活的组件显示在Html-代码片段中的位置"><a href="#2-RouterOutLet,路由插座,即:激活的组件显示在Html-代码片段中的位置" class="headerlink" title="2. RouterOutLet,路由插座,即:激活的组件显示在Html 代码片段中的位置"></a>2. RouterOutLet,路由插座,即:激活的组件显示在Html 代码片段中的位置</h3><h3 id="3-Router,路由对象,提供在控制器中使用的一系列方法"><a href="#3-Router,路由对象,提供在控制器中使用的一系列方法" class="headerlink" title="3. Router,路由对象,提供在控制器中使用的一系列方法"></a>3. Router,路由对象,提供在控制器中使用的一系列方法</h3><ul>
<li>navigate()</li>
<li>navigateByUrl()</li>
</ul>
<h3 id="4-RouterLink,在Html-中使用的导航指令"><a href="#4-RouterLink,在Html-中使用的导航指令" class="headerlink" title="4. RouterLink,在Html 中使用的导航指令"></a>4. RouterLink,在Html 中使用的导航指令</h3><h3 id="5-ActivatedRoute,当前激活的组件的路由对象"><a href="#5-ActivatedRoute,当前激活的组件的路由对象" class="headerlink" title="5. ActivatedRoute,当前激活的组件的路由对象"></a>5. ActivatedRoute,当前激活的组件的路由对象</h3><ul>
<li>路由地址</li>
<li>路由参数</li>
</ul>
<hr>
<h2 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h2><h3 id="1-配置项中,path-对象的值不能使用”-“-开头,这样可以使在项目中自由使用绝对路径和相对路径"><a href="#1-配置项中,path-对象的值不能使用”-“-开头,这样可以使在项目中自由使用绝对路径和相对路径" class="headerlink" title="1. 配置项中,path 对象的值不能使用”/“ 开头,这样可以使在项目中自由使用绝对路径和相对路径"></a>1. 配置项中,path 对象的值不能使用”/“ 开头,这样可以使在项目中自由使用绝对路径和相对路径</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">const router:Router = [</div><div class="line"> {</div><div class="line"> path:"product", //path:"/product",错误写法</div><div class="line"> component:ProductComponet</div><div class="line"> }</div><div class="line">];</div></pre></td></tr></table></figure>
<hr>
<h2 id="应用"><a href="#应用" class="headerlink" title="应用"></a>应用</h2><h3 id="1-RouterLink"><a href="#1-RouterLink" class="headerlink" title="1. RouterLink"></a>1. RouterLink</h3> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><a [RouterLink]="['/product']">GOTO</a></div></pre></td></tr></table></figure>
<ul>
<li>路由地址以’/‘ 开头,表示查找的是根目录组件</li>
<li>值的形式是数组,由路由地址和参数组成:[‘url’,参数]</li>
</ul>
<p>该写法等价于:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><a (click)="GOTO()">GOTO</a></div></pre></td></tr></table></figure></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">Controller:</div><div class="line">constructor(private router:Router){}</div><div class="line"> </div><div class="line">GOTO():void{</div><div class="line"> this.router.navigate(['/product'])</div><div class="line">}</div></pre></td></tr></table></figure>
<h3 id="2-基础写法"><a href="#2-基础写法" class="headerlink" title="2. 基础写法"></a>2. 基础写法</h3><ul>
<li>路由匹配是采取优先原则,通配符配置放在最后面,当路径错误是展现指定的页面<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">const router : Router =[</div><div class="line"> { path:"",component:HomeComponent }</div><div class="line"> { path:"product",component:Product }</div><div class="line"> { path:"**",component:404Component } //通配符配置</div><div class="line">]</div></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="3-参数的传递和接收"><a href="#3-参数的传递和接收" class="headerlink" title="3. 参数的传递和接收"></a>3. 参数的传递和接收</h3><p>路由参数传递的方式有三种,分别是:</p>
<p> ① 在查询参数中传递<br> ② 在路径中传递<br> ③ 在配置项中使用特定对象data传递</p>
<ul>
<li><p><strong>在查询参数中传递</strong><br>传递方式:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><a [routerLink]="['/product']" [queryParams]="{id:1}">GOTO</a></div></pre></td></tr></table></figure>
<p>接收方式:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">constructor(private routeInfo : ActivatedRoute){}</div><div class="line"></div><div class="line">private id : number;</div><div class="line"></div><div class="line">ngOnInit(){</div><div class="line"> this.id = this.routeInfo.snapshot.queryParams["id"];</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><p><strong>在路径中设置参数</strong><br>修改router中的配置:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">{ path:"product/:id", component:ProductComponent }</div></pre></td></tr></table></figure>
<p>修改Html中的RouterLink的写法:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line"><a [routerLink] = "['/product', 1]">GOTO</a></div></pre></td></tr></table></figure>
<p>Controller:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">this.id = this.routeInfo.snapshot.params["id"];</div></pre></td></tr></table></figure>
</li>
</ul>
<ul>
<li><strong>在路由的配置项中使用data对象</strong><br>修改路由配置项:<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div></pre></td><td class="code"><pre><div class="line">{</div><div class="line"> path:"product",</div><div class="line"> component:ProductComponent,</div><div class="line"> data:[</div><div class="line"> {id:1},</div><div class="line"> {name:2},</div><div class="line"> ]</div><div class="line">}</div></pre></td></tr></table></figure>
</li>
</ul>
<p> 获取传进来的参数:<br> <figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">constructor(private routeInfo: ActivatedRoute ){}</div><div class="line"></div><div class="line">ngOnInit(){</div><div class="line"> this.id = this.routeInfo.data[0]["id"];</div><div class="line">}</div></pre></td></tr></table></figure></p>
<hr>
<h2 id="参数快照和参数订阅"><a href="#参数快照和参数订阅" class="headerlink" title="参数快照和参数订阅"></a>参数快照和参数订阅</h2><p>通过路由激活某一个组件之后,获取参数的方式有两种</p>
<ul>
<li><p>参数快照,关键字:snapshot</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">ngOnInit(){</div><div class="line"> this.id = this.routeInfo.snapshot.params["id"];</div><div class="line">};</div></pre></td></tr></table></figure>
</li>
<li><p>参数订阅,关键字:subscribe</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">ngOnInit(){</div><div class="line"> this.routeInfo.params.subscribe((params : Params) => {</div><div class="line"> this.id = params["id"];</div><div class="line"> })</div><div class="line">};</div></pre></td></tr></table></figure>
<p><strong>参数订阅与参数快照的使用场景:</strong><br><em>当由HomeComponent进入到ProductComponent时,ProductComponent被激活,ngOnInit和constructor调用一次。<br> 例如:Product组件内部产品间的切换,由于id是通过参数在ngOnInit中获取的:<br> ①如果使用snapshot的方式,组件未被销毁,noOnInit不再执行,那么显示在外部的id值将不再更新,出现数据错误;<br> ②处理方式,采用subscribe的方式,当参数发生变化,即可更新信息;
</em></p>
</li>
</ul>
]]></content>
<summary type="html">
<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><h4 id="router是Angular-内置模块,可以使用cli-提供的指令来创建包含route-组件的项目"><a href="#rout
</summary>
</entry>
<entry>
<title>Angular 2(一): 概览</title>
<link href="https://github.com/tuluffy/2017/07/10/synopsis/"/>
<id>https://github.com/tuluffy/2017/07/10/synopsis/</id>
<published>2017-07-10T10:27:50.000Z</published>
<updated>2017-07-10T10:27:50.000Z</updated>
<content type="html"><![CDATA[<h2 id="新特性"><a href="#新特性" class="headerlink" title="新特性"></a>新特性</h2><h4 id="1-全新的命令行工具-angular-cli"><a href="#1-全新的命令行工具-angular-cli" class="headerlink" title="1. 全新的命令行工具 angular-cli"></a>1. 全新的命令行工具 <a href="https://www.npmjs.com/package/angular-cli" target="_blank" rel="external">angular-cli</a></h4><h4 id="2-服务端渲染"><a href="#2-服务端渲染" class="headerlink" title="2. 服务端渲染"></a>2. 服务端渲染</h4><ul>
<li>缩短页面从启动到完整展现的时间</li>
<li>解决seo问题</li>
</ul>
<h4 id="3-提供了标准的UI库(Material-Design),使桌面和移动程序兼容"><a href="#3-提供了标准的UI库(Material-Design),使桌面和移动程序兼容" class="headerlink" title="3. 提供了标准的UI库(Material Design),使桌面和移动程序兼容"></a>3. 提供了标准的UI库(Material Design),使桌面和移动程序兼容</h4><h4 id="4-核心:组件、服务、指令-gt-功能-模块-gt-打包"><a href="#4-核心:组件、服务、指令-gt-功能-模块-gt-打包" class="headerlink" title="4. 核心:组件、服务、指令 =>功能, 模块=>打包"></a>4. 核心:组件、服务、指令 =>功能, 模块=>打包</h4><hr>
<h2 id="工程目录关键文件介绍"><a href="#工程目录关键文件介绍" class="headerlink" title="工程目录关键文件介绍"></a>工程目录关键文件介绍</h2><h3 id="1-angular-cli-json"><a href="#1-angular-cli-json" class="headerlink" title="1. .angular-cli.json"></a>1. .angular-cli.json</h3><p>angular 命令行工具配置文件,Angular应用程序启动的入口,引入第三方库需要在此处配置</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line">"apps": [</div><div class="line"> {</div><div class="line"> "root": "src",</div><div class="line"> //配置外部css文件</div><div class="line"> "styles": [</div><div class="line"> "styles.css",</div><div class="line"> "../node_modules/bootstrap/dist/css/bootstrap.css"</div><div class="line"> ],</div><div class="line"> //配置外部js文件</div><div class="line"> "scripts": [</div><div class="line"> "../node_modules/jquery/dist/jquery.js", //配置JQ,注意路径问题,以root为基地址</div><div class="line"> "../node_modules/bootstrap/dist/js/bootstrap.js" </div><div class="line"> ],</div><div class="line"> }</div><div class="line"> ],</div></pre></td></tr></table></figure>
<hr>
<h2 id="工程模块介绍"><a href="#工程模块介绍" class="headerlink" title="工程模块介绍"></a>工程模块介绍</h2><h3 id="1-Component,-装饰器"><a href="#1-Component,-装饰器" class="headerlink" title="1. @Component, 装饰器"></a>1. @Component, 装饰器</h3><ul>
<li>用来告知框架如何处理一个ts类</li>
<li>Component中所有属性的值称为元数据</li>
<li>Angular根据元数据渲染组件,并实现控制器的逻辑</li>
</ul>
<h3 id="2-Template,模板,可以简单地理解为可使用Angular数据绑定机制的html片段"><a href="#2-Template,模板,可以简单地理解为可使用Angular数据绑定机制的html片段" class="headerlink" title="2. Template,模板,可以简单地理解为可使用Angular数据绑定机制的html片段"></a>2. Template,模板,可以简单地理解为可使用Angular数据绑定机制的html片段</h3><h3 id="3-Controller,控制器"><a href="#3-Controller,控制器" class="headerlink" title="3.Controller,控制器"></a>3.Controller,控制器</h3><ul>
<li>被@Component装饰器用来装饰</li>
<li>通过数据绑定和模板通信</li>
</ul>
<hr>
<h2 id="模块(NgModel)相关介绍"><a href="#模块(NgModel)相关介绍" class="headerlink" title="模块(NgModel)相关介绍"></a>模块(NgModel)相关介绍</h2><h3 id="1-declarations,我们定义的组件、指令、管道需要放在此处声明"><a href="#1-declarations,我们定义的组件、指令、管道需要放在此处声明" class="headerlink" title="1. declarations,我们定义的组件、指令、管道需要放在此处声明"></a>1. declarations,我们定义的组件、指令、管道需要放在此处声明</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">declarations: [</div><div class="line"> AppComponent,</div><div class="line"> ProductComponent,</div><div class="line">],</div></pre></td></tr></table></figure>
<h3 id="2-imports,声明应用正常运转需要的模块,也即:AppModule所依赖的模块"><a href="#2-imports,声明应用正常运转需要的模块,也即:AppModule所依赖的模块" class="headerlink" title="2. imports,声明应用正常运转需要的模块,也即:AppModule所依赖的模块"></a>2. imports,声明应用正常运转需要的模块,也即:AppModule所依赖的模块</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line">imports: [</div><div class="line"> BrowserModule,</div><div class="line"> HttpModule,</div><div class="line"> FormsModule,</div><div class="line">],</div></pre></td></tr></table></figure>
<h3 id="3-provides,相关服务放在此种声明"><a href="#3-provides,相关服务放在此种声明" class="headerlink" title="3. provides,相关服务放在此种声明"></a>3. provides,相关服务放在此种声明</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">providers: [</div><div class="line"> HttpService, //服务类名称</div><div class="line">],</div></pre></td></tr></table></figure>
<h3 id="4-bootstrap,声明启动组件"><a href="#4-bootstrap,声明启动组件" class="headerlink" title="4. bootstrap,声明启动组件"></a>4. bootstrap,声明启动组件</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">bootstrap: [</div><div class="line"> AppComponent,</div><div class="line">]</div></pre></td></tr></table></figure>
]]></content>
<summary type="html">
<h2 id="新特性"><a href="#新特性" class="headerlink" title="新特性"></a>新特性</h2><h4 id="1-全新的命令行工具-angular-cli"><a href="#1-全新的命令行工具-angular-cli" cla
</summary>
</entry>
</feed>