<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                在現實生活中,感知數據變化的方式有兩種,第一種是**數據監聽**,第二種是**觀察者模式**。 以在京東購物為例,假設你最有購買一塊CPU的需求,由于口袋不太滿,所以想在搞活動的時候購買。滿足此需求有兩種實現的方式。 第一種:我們可以每天睡前打開京東看看價格。如果有一天CPU的價格達到了自己心中的預期,便可以購買了。這就是最典型的數據監聽。 第二種:我們可以在對應的商品上點擊降價提醒按鈕,并輸入自己心中的一個預期價格。此后,一旦CPU降到了我們預期的價格,我們則會收到一個降價的通知。而這便是我們說的**觀察者模式**。 > 如果**觀察者模式**不太容易理解,也可以記憶為**訂閱者模式**、**關注者模式**,想想各種求訂閱、求關注的情景,相信這種模式便不難理解了吧。 如果你也是我這樣的懶人,相信也一定會選擇第二種模式。這種模式可以使我們能夠再懶一些,對于計算機而言,這種懶對應的便是:占用資源更低、效率更高。 ## 偉大的Angular 偉大的Agnular并不僅僅是一個前端的框架,它還是先進編程思想的傳播者!這種感受會隨著我們接觸Angular的時間而逐步加深。 ## 響應式表單 響應式表單在數據監聽方面實現了**觀察者模式**,在此模式的支持下,數據變化時我們可以得到一個通知。接下來我們使用響應式表單對教師選擇組件進行改造。 ```typescript +++ b/first-app/src/app/clazz/klass-select/klass-select.component.ts @@ -1,6 +1,7 @@ import {Component, OnInit, EventEmitter, Output} from '@angular/core'; import {Teacher} from '../../entity/teacher'; import {HttpClient} from '@angular/common/http'; +import {FormControl} from '@angular/forms'; @Component({ @@ -10,7 +11,7 @@ import {HttpClient} from '@angular/common/http'; }) export class KlassSelectComponent implements OnInit { teachers = new Array<Teacher>(); - teacherId: number | undefined; + teacherId = new FormControl(); @Output() beChange = new EventEmitter<number>(); @@ -23,10 +24,4 @@ export class KlassSelectComponent implements OnInit { this.httpClient.get<Array<Teacher>>('teacher') .subscribe(teachers => this.teachers = teachers); } - - onChange(): void { - console.log('change called'); - console.log(this.teacherId); - this.beChange.emit(this.teacherId); - } } ``` 如上所示:使用對象`FormControl`來替代原來的`number`類型,并刪除原來的`onChange`方法。然后對V層進行如下改造: ```html +++ b/first-app/src/app/clazz/klass-select/klass-select.component.html @@ -1,7 +1,5 @@ <select id="teacher" class="form-control" - name="teacher" - [(ngModel)]="teacherId" - (change)="onChange()"> + [formControl]="teacherId"> <option *ngFor="let teacher of teachers" [ngValue]="teacher.id"> {{teacher.name}} </option> ``` `formControl`并不要求表單項必須有`name`,在此我們一并刪除了`name`屬性。接下來向班級模塊中添加響應式表單所在的模塊`ReactiveFormsModule`: ```typescript +++ b/first-app/src/app/clazz/clazz.module.ts @@ -1,7 +1,7 @@ import {NgModule} from '@angular/core'; import {CommonModule} from '@angular/common'; import {AddComponent} from './add/add.component'; -import {FormsModule} from '@angular/forms'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; import { KlassSelectComponent } from './klass-select/klass-select.component'; @@ -9,7 +9,8 @@ import { KlassSelectComponent } from './klass-select/klass-select.component'; declarations: [AddComponent, KlassSelectComponent], imports: [ CommonModule, - FormsModule + FormsModule, + ReactiveFormsModule ] }) export class ClazzModule { ``` 最后,向單元測試的動態測試模塊中也添加`ReactiveFormsModule`模塊: ```typescript +++ b/first-app/src/app/clazz/klass-select/klass-select.component.spec.ts -import {FormsModule} from '@angular/forms'; +import {FormsModule, ReactiveFormsModule} from '@angular/forms'; imports: [ HttpClientModule, - FormsModule + FormsModule, + ReactiveFormsModule ], ``` ### 測試 啟動單元并查看效果,查看控制臺是否有報錯信息: ![image-20210324084043748](https://img.kancloud.cn/ff/ab/ffab5f83c4049bc5e37438562aa276db_964x188.png) 小結:直接在表單中使用`[(ngModel)]`雖然便捷,但卻不夠**正綜**。Angular的前身AngularJS嘗經廣泛的使用了這種`ngModel`數據綁定方式,當年也獲取了很大的成功。但這種方式也會帶來不小的開銷,當項目稍大的時,便會暴露出性能上的弊端。Angular中啟用了全新的**響應式表單**來替換原`ngModel`的綁定方式,但可能是出于照顧使用AngularJS的歷史用戶,使他們在升級時能夠減小一點點負擔,所以在新的Angular中仍然支持了這種模式。 ## 訂閱數據變化 下面,我們展示如何來**關注**`teacherId`這個`FormControl`以成為它的粉絲,這樣一來,當它有新的動態時便會給我們發送通知了。 ```typescript +++ b/first-app/src/app/clazz/klass-select/klass-select.component.ts @@ -20,6 +20,9 @@ export class KlassSelectComponent implements OnInit { } ngOnInit(): void { + // 關注teacherId + this.teacherId.valueChanges + .subscribe((data: number) => this.beChange.emit(data)); // 獲取所有教師 this.httpClient.get<Array<Teacher>>('teacher') .subscribe(teachers => this.teachers = teachers); ``` `valueChanges`是`FormControl`提供的一個可對其進行關注的屬性,我們只需要調用`valueChanges`上的`subscribe`方法,便完成了對數據的**關注**。當有新的數據時,我們傳入的訂閱方法將被執行,數據成功由beChange彈射器彈出給父組件。 ## 測試 我們像以往的測試一樣選擇教師: ![image-20210324084043748](https://img.kancloud.cn/ff/ab/ffab5f83c4049bc5e37438562aa276db_964x188.png) 選擇的教師變更后,接收到了彈出的數據。 ![image-20210325161027648](https://img.kancloud.cn/8e/15/8e150d3277dc1c338d1077b359eba282_1260x268.png) ## 總結 本節中,我們使用響應式表單的`FormControl`對象來替換了原`number`類型。在與V層的綁定上`FormControl`并不要求表單項必須存在`name`屬性。 在監聽數據變化方法,響應式表單使用了觀察者模式。 我們雖然還沒有感受到這種模式給我們帶來的好處。但相對于原`change()`方法,最少在代碼量上有所降低。 在后續的章節中,我們會千篇一律的使用響應表單,相信你會逐步的感受它的魅力。 | 名稱 | 鏈接 | | ------------ | ------------------------------------------------------------ | | 響應式表單 | [https://angular.cn/guide/reactive-forms#reactive-forms](https://angular.cn/guide/reactive-forms#reactive-forms) | | valueChanges | [https://angular.cn/api/forms/AbstractControl#valueChanges](https://angular.cn/api/forms/AbstractControl#valueChanges) | | 本節源碼 | [https://github.com/mengyunzhi/angular11-guild/archive/step6.2.2.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.2.2.zip) |
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看