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

                # 數據驗證 本節我們對新建班級時的班級名稱進行非空驗證,力求達到以下目標: 1. 模擬API模擬后臺對數據進行驗證。 2. 班級名稱為空時,不允許點擊提交按鈕。 3. 未選擇班主任時,不允許點擊提交按鈕。 ### MockApi 一個好的MockApi往往會處理一些邏輯,特別是在數據的校驗方面。而完成數據校驗的前提是獲取到這些數據。在第2小節中我們引入了能夠模似后臺API的MockApi,版本為`0.0.3`。本節中我們需要一些`0.0.5`版本的新特性,則需要對原依賴進行一些升級操作。 ## 升級依賴 維護一個項目使其**不過時**是一種負責任的行為。相信在大家學習此教程時,執行`npm install`或多或少的都會看到一些依賴過時或有風險的提示: ```bash found 2 moderate severity vulnerabilities run `npm audit fix` to fix them, or `npm audit` for details ``` 升級這些依賴的方法有很多,在此給出一種雖然笨但有效的方法。 我們知道`package.json`中控制著當前項目的所有依賴,那么我們當然可以簡單的直接修改`package.json`中相關依賴的代碼了。比如我們打開`package.json`將MockApi依賴由`0.0.3`版本修改為`0.0.5`版本。 ```json +++ b/first-app/package.json @@ -20,7 +20,7 @@ "@angular/platform-browser-dynamic": "~11.0.9", "@angular/router": "~11.0.9", "@fortawesome/fontawesome-free": "^5.15.2", - "@yunzhi/ng-mock-api": "0.0.3", + "@yunzhi/ng-mock-api": "0.0.5", "bootstrap": "^4.6.0", "jquery": "^3.5.1", "popper.js": "^1.16.1", ``` 然后在項目根目錄中執行`npm install`來重新安裝項目依賴,此時`@yunzhi/ng-mock-api`的版本便成功更新于`0.0.5`了。 使用`npm install`命令時會下載一些依賴至項目根目錄的`node_modules`文件夾中。我們在其下可以找到一個`@yunzhi/ng-mock-api`文件夾。 ``` panjie@panjies-Mac-Pro first-app % tree node_modules/@yunzhi -L 2 node_modules/@yunzhi └── ng-mock-api ├── README.md ├── bundles ├── esm2015 ├── fesm2015 ├── lib ├── package.json ?? ├── public-api.d.ts ├── testing ├── yunzhi-ng-mock-api.d.ts └── yunzhi-ng-mock-api.metadata.json ``` 該文件夾中的`package.json`記錄著當前依賴的具體信息,也包括版本號。 ```json "sideEffects": false, "typings": "yunzhi-ng-mock-api.d.ts", "version": "0.0.5" ?? } ``` 除此以外,還可以搜索`npm update package`或`npm update dependencies`來獲取更多關于升級項目依賴的知識: ![image-20210319144803328](https://img.kancloud.cn/cb/68/cb684dc14cb076a97e990c43981b49d9_2094x184.png) ## 數據校驗 創建MockApi時,我們將模擬的結果放到了`result`屬性上: ```typescript class ClazzMockApi implements MockApiInterface { getInjectors(): ApiInjector<any>[] { return [ { method: 'POST', url: 'clazz', result: { ?? id: 1, name: '保存的班級名稱', createTime: 1234232, teacher: { id: 1, name: '教師姓名' } } } ]; } } ``` `result`屬性除可設置為一般的變量以外,還可以將其設置為函數: ```typescript result: () => { return { id: 1, name: '保存的班級名稱', createTime: 1234232, teacher: { id: 1, name: '教師姓名' } }; } ``` 這兩種寫法效果一致,運行單元測試我們當得到相同的結果: ![image-20210319093210533](https://img.kancloud.cn/2b/00/2b00fe07a1d2cda0e0ecc17f151d2393_1244x198.png) 但設置為函數時,我們在函數上指定相關參數,這些參數的值可以幫助我們實現更靠近其實環境的邏輯: ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -1,7 +1,7 @@ import {AddComponent} from './add.component'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http'; -import {ApiInjector, MockApiInterceptor, MockApiInterface} from '@yunzhi/ng-mock-api'; +import {ApiInjector, MockApiInterceptor, MockApiInterface, RequestOptions} from '@yunzhi/ng-mock-api'; import {FormsModule} from '@angular/forms'; describe('clazz add with mockapi', () => { @@ -42,7 +42,7 @@ class ClazzMockApi implements MockApiInterface { { method: 'POST', url: 'clazz', - result: () => { + result: (urlMatches: string[], options: RequestOptions) => { return { id: 1, name: '保存的班級名稱', ``` 其中`urlMatches`為請求URL的相關信息,`options`包括了請求主體、請求headers等信息。我們此時預實現請求的數據驗證功能,則正好需要這個請求主體: ```typescript result: (urlMatches: string[], options: RequestOptions) => { + console.log('接收到了數據請求,請求主體的內容為:', options.body); ``` ![image-20210319151625649](https://img.kancloud.cn/9f/cf/9fcf4718544b388233896f5a643b66cb_1318x230.png) 數據接收到后:當數據符合要求,則返回數據;如果不符合要求,則拋出一個異常。 ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -44,6 +44,15 @@ class ClazzMockApi implements MockApiInterface { url: 'clazz', result: (urlMatches: string[], options: RequestOptions) => { console.log('接收到了數據請求,請求主體的內容為:', options.body); + const clazz = options.body; + if (!clazz.name || clazz.name === '') { + throw new Error('班級名稱未定義或為空'); + } + + if (!clazz.teacher || !clazz.teacher.id) { + throw new Error('班主任ID未定義'); + } + return { id: 1, name: '保存的班級名稱', ``` 該異常將導致新班級保存失敗: ![image-20210319152607494](https://img.kancloud.cn/9f/07/9f0775ff90a336fd49d06dd61263ea2f_1032x106.png) ### 完善模擬數據 下面我們再對模擬返回數據進行修正,讓其返回更**合理**的模擬數據: ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -1,7 +1,7 @@ import {AddComponent} from './add.component'; import {ComponentFixture, TestBed} from '@angular/core/testing'; import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http'; -import {ApiInjector, MockApiInterceptor, MockApiInterface, RequestOptions} from '@yunzhi/ng-mock-api'; +import {ApiInjector, MockApiInterceptor, MockApiInterface, randomNumber, RequestOptions} from '@yunzhi/ng-mock-api'; import {FormsModule} from '@angular/forms'; describe('clazz add with mockapi', () => { @@ -52,13 +52,13 @@ class ClazzMockApi implements MockApiInterface { if (!clazz.teacher || !clazz.teacher.id) { throw new Error('班主任ID未定義'); } - + return { - id: 1, + id: randomNumber(), name: '保存的班級名稱', - createTime: 1234232, + createTime: new Date().getTime(), teacher: { - id: 1, + id: clazz.teacher.id, name: '教師姓名' } }; ``` 使用`randomNumber()`來生成一個隨機的數字作為返回班級的id,這更貼近于生產環境;`createTime`設置為當前的時間,使數據看起來更真實,而`teacher`的`id`使入接收到的`id`,也是必要的。這樣一樣,返回數據看起來就正常的多了。 此時,我們在測試提交的教師id時,在也不必拘泥于**張三**、**李四**對應的`id=1`,`id = 2`了。在單元測試中完全可以設置一個隨機教師id: ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -29,6 +29,8 @@ describe('clazz add with mockapi', () => { }); fit('在MockApi下完成組件測試Submit', () => { + component.clazz.name = '測試班級名稱'; + component.clazz.teacherId = randomNumber(); component.onSubmit(); }); }); ``` 如此一來,一個合格的后臺API替身便誕生了: ![image-20210319153043698](https://img.kancloud.cn/4d/13/4d135c95ecc9cb5790067fa38a661dc6_1392x336.png) ## V層測試 在啟用fixture的自動檢測變更后,如果未輸入班級名稱或未選擇教師就點擊保存按鈕的話,將在控制臺得到相應的錯誤信息: ```typescript +++ b/first-app/src/app/clazz/add/add.component.mock-api.spec.ts @@ -28,11 +28,15 @@ describe('clazz add with mockapi', () => { fixture.detectChanges(); }); - fit('在MockApi下完成組件測試Submit', () => { + it('在MockApi下完成組件測試Submit', () => { component.clazz.name = '測試班級名稱'; component.clazz.teacherId = randomNumber(); component.onSubmit(); }); + + fit('should create', () => { + fixture.autoDetectChanges(); + }); }); /** ``` ![image-20210319153352871](https://img.kancloud.cn/72/c9/72c9461ad1ab9bd06a929eea1e4d8e7f_1582x570.png) 這幾乎與真正的后臺表示無異。 ## disabled Angular的FormsModule支持button標簽的disabled屬性,當此屬性為true時按鈕不可用,為false時按鈕可用。我們可以利用此特性,實現名稱為空、未選擇班主任時的禁止提交功能。 ```html +++ b/first-app/src/app/clazz/add/add.component.html @@ -19,7 +19,9 @@ </div> <div class="mb-3 row"> <div class="col-sm-10 offset-2"> - <button class="btn btn-primary">保存</button> + <button class="btn btn-primary" + [disabled]="clazz.name === '' || clazz.teacherId === null">保存 + </button> </div> </div> </form> ``` 此時,再啟用fixture的自動檢測變更后,V層中的按鈕將只在班級名稱不為空且選擇了teacher后可用。 ![image-20210319140010101](https://img.kancloud.cn/92/3b/923bc32f17ea0839cc9c00bdc2c9c9f8_1468x314.png) 填寫班級名稱,并選擇班主任后: ![image-20210319140036645](https://img.kancloud.cn/75/6d/756d9107cdf13616182e4b7f283aaf61_1100x328.png) 在模擬后臺API的數據校驗以及V層按鈕disabled的表現下,我們再也不怕客戶不按照我們指定的使用方式來使用系統了。 ## 本節作業 請實現以下效果: 1. 初始化時提示名稱及班主任不能為空: ![image-20210319154000907](https://img.kancloud.cn/d7/aa/d7aa3b558ba78d7cbad593ba43db4f69_1478x328.png) 2. 填寫完相應的內容后,提示消失: ![image-20210319140036645](https://img.kancloud.cn/75/6d/756d9107cdf13616182e4b7f283aaf61_1100x328.png) | 名稱 | 鏈接 | | -------- | ------------------------------------------------------------ | | 本節源碼 | [https://github.com/mengyunzhi/angular11-guild/archive/step6.1.4.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.1.4.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>

                              哎呀哎呀视频在线观看