<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>

                # ?教師選擇列表 前面的小節中選擇班主任時,我們手寫了張三、李四兩個教師信息。顯然這與實際的需求是不相符的。在教師選擇組件中,我們希望顯示當前系統的所有教師。 本節我們將在MockApi的支持下,模擬由后臺獲取所有教師數據,然后在此基礎上,打造一個真實的教師選擇列表。 ## 初始化 開發新的組件離不開原型的初始化,開發新功能也是如此,這有利于我們掌握真實的功能需求。 ## C層初始化 教師列表組件需要顯示所有的教師信息,所以我們在C層初始化一個教師的數組: ```typescript +++ b/first-app/src/app/clazz/add/add.component.ts @@ -13,6 +13,8 @@ export class AddComponent implements OnInit { teacherId: null as unknown as number }; + teachers = []; + constructor(private httpClient: HttpClient) { } ``` 既然是初始化,我們還是希望能夠看到一些效果的。根據當前V層的教師列表相關代碼: ```html <select id="teacher" class="form-control" name="teacher" [(ngModel)]="clazz.teacherId"> <option [ngValue]="1">張三</option> <option [ngValue]="2">李四</option> </select> ``` 我們確認一個教師列表選擇功能,需要教師的兩個屬性:1. 教師id;2.教師姓名。據此,我們在C層中初始化這兩項信息: ```typescript - teachers = []; + teachers = [ + { + id: 1, + name: '張三' + }, + { + id: 2, + name: '李四' + } + ]; ``` 直接使用`[]`來對數組初始化顯示比較方法,但這樣做卻使TypeScript強類型的優勢完全失效。所以在定義數組時,正確的做法應該是 `teachers = new Array<Teacher>;` ```typescript import {Teacher} from '../../entity/teacher'; teachers = new Array<Teacher>( { id: 1, name: '張三' }, { id: 2, name: '李四' } ); ``` TypeScript的強類型能夠防止我們犯一些拼寫方面的錯誤,比如我們在此將數組的元素類型約束為Teacher后,會在IDE下發現如下錯誤提醒: ![image-20210322101959790](https://img.kancloud.cn/1b/f0/1bf047ec894f3e05866688be47acf6d4_2108x524.png) 這是在告訴我們:當前數組中的元素類型應該為Teacher,則其中的每一項的類型都應該是Teacher。Teacher的類型中除了`id`,`name`屬性以外,還存在著`email` 、`password`、`sex`、`username`屬性。 消除該提示有多種方法,最簡單方法是加入`email`等屬性,比如: ```typescript { id: 1, name: '張三', email: 'zhangsan@yunzhi.club', username: 'zhangsan', sex: true, password: '' }, ``` 但是我們明明只需要`id`,`name`就可以了,初始化時加入其它不需要的屬性便是畫蛇添足了。在這種僅需要某幾個屬性的情況下,我們往往使用`as`來進行類型的轉換來消除此類錯誤。 ```typescript teachers = new Array<Teacher>( { id: 1, name: '張三' } as Teacher, { id: 2, name: '李四' } as Teacher ); ``` ## V層初始化 V層的實現則可以使用我們前面學習過的`ngFor`指令: ```html +++ b/first-app/src/app/clazz/add/add.component.html @@ -16,8 +16,9 @@ <select id="teacher" class="form-control" name="teacher" [(ngModel)]="clazz.teacherId"> - <option [ngValue]="1">張三</option> - <option [ngValue]="2">李四</option> + <option *ngFor="let teacher of teachers" [ngValue]="teacher.id"> + {{teacher.name}} + </option> </select> <small class="text-danger" *ngIf="clazz.teacherId === null"> ``` ## 測試 使用`ng t`在`add.component.spec.ts`或`add.component.mock-api.spec.ts`的支持下,對上述代碼進行測試。比如我們以`add.component.spec.ts`做為測試文件,將`it`變更為`fit`: ```typescript fit('should create', () => { expect(component).toBeTruthy(); fixture.autoDetectChanges(); }); ``` ![image-20210322103940085](https://img.kancloud.cn/2f/67/2f67c22ec0408ed9af79b21ac2940fa1_706x290.png) 在開發某個組件時,應該時刻保持僅有一個測試用例生效,也就是整個項目中,最多存在一個`fit`。 ![image-20210322104045306](https://img.kancloud.cn/09/bd/09bde2516aa6e5347dd04a1eb4cf96e0_2410x208.png) ## 對接后臺 初始化完成了、效果也有了,接下來便是正式的對接后臺。既然是正式對接后臺,那么C層中則僅需要初始化一個空的教師數組即可: ```typescript +++ b/first-app/src/app/clazz/add/add.component.ts @@ -14,16 +14,7 @@ export class AddComponent implements OnInit { teacherId: null as unknown as number }; - teachers = new Array<Teacher>( - { - id: 1, - name: '張三' - } as Teacher, - { - id: 2, - name: '李四' - } as Teacher - ); + teachers = new Array<Teacher>(); constructor(private httpClient: HttpClient) { } ``` 接下來調用后臺API獲取全部教師。獲取所有教師的API我們在前面的章節中已經給出了,為`GET /teacher`。在Angular中,若想在組件初始化后執行某些代碼,則僅需要將該代碼添加到`ngOnInit`方法中(這也是已經講過的知識,相信你一定還記得): ```typescript +++ b/first-app/src/app/clazz/add/add.component.ts @@ -20,6 +20,9 @@ export class AddComponent implements OnInit { } ngOnInit(): void { + // 獲取所有教師 + this.httpClient.get('teacher') + .subscribe(teachers => this.teachers = teachers); } ``` 上述代碼從理論上來講是沒有任何問題的:我們通過GET方法來獲取全部的教師數據,然后在將其賦值給當前組件的teachers屬性。但是TypeScript卻讀不懂我們心中所想,由于`httpClient.get`返回的數據類型被定義為`Object`,所以以下代碼實際上是在將一個類型為`Object`的變量賦值為類型為`Array<Teacher>`的變量。 ```typescript this.httpClient.get('teacher') .subscribe(teachers 類型為Object) => this.teachers 類型為Array<Teacher> = teachers 類型為Object); ``` `Object`類型是個0屬性的對象,比如`{}`的類型便是`Object` ,在面向對象的世界里,它是最**小**的小弟。所以只要是個對象,便可以轉換為Object,而Object卻不能轉換為其它任意非Object類型。 TypeScript聰明的發現了這一點,它在告訴我們說:類型Object這個最小的小弟,怎么能轉換為`Array<Teacher>`這個大哥呢? ![image-20210322105832384](https://img.kancloud.cn/d8/77/d877f7183b78aa6702b2236f5bbe21a7_2340x266.png) 為了解決這一問題,httpClient除提供了`get()`方法外,還提供了一個可以指定返回值類型的`get<T>()`: ```typescript // 獲取所有教師 this.httpClient.get<Array<Teacher>>('teacher') .subscribe(teachers => this.teachers = teachers); ``` 此時TypeScript就明白了:原來在此處進行`get`方法的請求,將得到一個類型為`Array<Teacher>`的返回數據。該類型與當前組件聲明的`teachers`類型相同,錯誤自然也就消失了。 此時在`add.component.spec.ts`測試文件的支持下,打開瀏覽器控制臺,發現發起了真實的網絡請求,并且在教師列表中顯示了后臺擁有的教師列表: ![image-20210322110456557](https://img.kancloud.cn/df/e9/dfe9e09b58e849c03db59475becbe02b_994x214.png) ![image-20210322104045306](https://img.kancloud.cn/09/bd/09bde2516aa6e5347dd04a1eb4cf96e0_2410x208.png) **注意**:我們在這里所說的**返回值**,并不是指函數的返回值,而是特指在發起http請求時,后臺返回來的值。 ## Mock測試 我們剛剛非常**幸運**的利用真實的后臺API完成了教師選擇的功能。之所以說幸運,是由于后臺這個接口即不需要先完成用戶登錄,又不需要滿足任何的前提。但真實的生產環境中,我們卻很少碰到這樣的情況。如果是在MockApi的情況下,又該如何測試呢? 為此我們移除`add.component.spec.ts`的`fit`,啟用`add.component.mock-api.spec.ts`的相關測試用例: ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -34,7 +34,7 @@ describe('clazz add with mockapi', () => { component.onSubmit(); }); - it('should create', () => { + fit('should create', () => { fixture.autoDetectChanges(); }); }); ``` 然后我們簡單思索一會,想像一下可能會發生什么樣的錯誤,又為什么會發生這樣的錯誤。思索完成后打開控制臺來驗證自己的錯誤并嘗試解決。 | 名稱 | 地址 | 備注 | | ---------------------- | ------------------------------------------------------------ | -------- | | TypeScript基礎類型 | [https://www.tslang.cn/docs/handbook/basic-types.html](https://www.tslang.cn/docs/handbook/basic-types.html) | 必學內容 | | 請求輸入一個類型的響應 | [https://angular.cn/guide/http#requesting-a-typed-response](https://angular.cn/guide/http#requesting-a-typed-response) | | | 本節源碼 | [[https://github.com/mengyunzhi/angular11-guild/archive/step6.1.5.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.1.5.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>

                              哎呀哎呀视频在线观看