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

                我們在前面的小節中成功地引用了`HttpClient`并使用其發起了數據請求,最終將請求的數據成功的顯示到了界面上。在此過程中,我們普遇到過如下錯誤: ![](https://img.kancloud.cn/5b/e7/5be7e7416ffc7f6a908954fabdbe2905_575x68.png) 最終通過在測試文件的imports中加入了HttpClientModule將該錯誤消除。本節我們將重點討論一下為什么引入了HttpClientModule后錯誤就消息了。 在繼續學習以前,我們暫時移除測試文件`app.component.spec.ts`中對`HttpClientModule`的引入: ```typescript imports: [ RouterTestingModule, HttpClientModule ? ], ``` * ? 刪除該行 此時`ng t`將報如下錯誤: ![](https://img.kancloud.cn/57/42/57421d179f3d9392b2078e06c72f4263_606x67.png) # 錯在哪 解決問題的前提是弄明白產生問題的原因,找到問題產生的原因的前提是找到出錯代碼的位置。為了弄清楚到底是哪行代碼導致的異常,我們只保留該測試中的第一行代碼: ```typescript it('組件初始化', () => { const fixture = TestBed.createComponent(AppComponent); // const app = fixture.componentInstance; // expect(app).toBeTruthy(); // // // 啟用angular的自動變更檢測機制,自動對V層中的數據進行渲染 // fixture.autoDetectChanges(); }); ``` ![](https://img.kancloud.cn/57/42/57421d179f3d9392b2078e06c72f4263_606x67.png) 異常依舊,此時我們大概可以確認是第一行代碼出現了問題。為了避免誤殺,我們在將第一行代碼也注釋掉: ```typescript it('組件初始化', () => { // const fixture = TestBed.createComponent(AppComponent); // const app = fixture.componentInstance; // expect(app).toBeTruthy(); // // 啟用angular的自動變更檢測機制,自動對V層中的數據進行渲染 // fixture.autoDetectChanges(); }); ``` ![](https://img.kancloud.cn/1d/74/1d74189bc61a752344c5880ab01acd5c_611x77.png) 錯誤消失,則可以完全確認是第一行代碼出了問題。隨后移除剛剛第一行代碼的注釋后,我們繼續學習。 >[success] 當發生一些預期以外的問題時,分塊注釋是個解決問題的好辦法。 ## 組件初始化 對組件進行測試的前提是創建一個組件,而創建組件的過程中必然離不開組件的實例化。為了更好的理解這一過程,我們對單元測試中的相關代碼并添加相應注釋如下: ```typescript it('組件初始化', () => { // 創建一個夾具,該夾具中實例化了一個AppComponent對象 const fixture = TestBed.createComponent(AppComponent); // 獲取夾具中的AppComponent對象 // const app = fixture.componentInstance; // 預測上述過程沒有發生錯誤,即成功獲取到了AppComponent對象 // expect(app).toBeTruthy(); // 啟用angular的自動變更檢測機制,自動對V層中的數據進行渲染 // fixture.autoDetectChanges(); ``` `TestBed.createComponent(AppComponent)`的流程圖大體如下: ![](https://img.kancloud.cn/9f/87/9f872b7ab8d76cd32159d6bc49cf8722_475x385.png) 通過該圖片可以得出結論:錯誤產生的原因于Angular在能力初始化的過程中沒有設置提供`HttpClient`的能力。 而這個能力設置的對象,就是本節中我們將討論的**模塊**。 # 模塊 在Angular中**模塊**是可獨立運行的最小單元,比如我們在src/app文件夾中的app.module.ts的作用就是在聲明一個**模塊**。 ```bash . ├── app-routing.module.ts ├── app.component.css ├── app.component.html ├── app.component.spec.ts ├── app.component.ts └── app.module.ts ?? ``` **組件**依賴于**模塊**,存在于**模塊**,組件若想成動運行,則必然是運行于某個**模塊**之中。組件成功運行的前提,是在**模塊**中被成功地實例化,**模塊**能夠成功實例化某個**組件**的前提是**模塊**擁有**組件**想要的一切。 ![](https://img.kancloud.cn/04/11/041113da69fe9cf930c935442c56486b_336x104.png) ## 測試模塊 在單元測試中,我們通過以下代碼創建一個測試模塊: ```typescript beforeEach(async () => { await TestBed.configureTestingModule({ imports: [ RouterTestingModule, ], declarations?: [ AppComponent? ], }).compileComponents(); }); ``` 通過在?declarations中聲明?AppComponent來表示:AppComponent組件屬于當前測試模塊。當單元測試發生錯誤時,我們可以查看到當前測試模塊的身影。 ![](https://img.kancloud.cn/bb/ca/bbcae41a724713bf0ebe6137734942e4_566x42.png) 它的名稱為DynamicTestModule,即動態測試模塊,即為當前AppComponent組件所在模塊。 一個**模塊**擁有什么樣的能力,除可以在`declarations`中聲明自身擁有的能力以外,還可以在`imports`引用外部的資源。比如當前引入了`RouterTestingModule`,則當前模塊擁有`RouterTestingModule`提供的相關能力。 ```typescript imports: [ RouterTestingModule, ], ``` 由于我們要測試的`AppComponent`并不依賴于任何`RouterTestingModule`提供的能力,所以在此我們可以將其引入的代碼刪除。 ```typescript import {RouterTestingModule} from '@angular/router/testing'; ? ... imports: [ RouterTestingModule, ? ], ``` ## HttpClientModule `declarations`與`imports`不同的是,前者僅能夠聲明`組件`等**模塊**的成員,而后者則是聲明的其它**模塊**。 與當前**動態測試模塊**相同,**HttpClientModule**也是一個模塊,該模塊下有一個**可用**的**HttpClient**成員,所以當我們將`HttpClientModule`加入到`imports`中時: ```typescript imports: [ HttpClientModule ], ``` 相當于: ![](https://img.kancloud.cn/0d/e3/0de386bb8e7c287381f26c3dad004b50_391x181.png) 此時動態測試模塊便擁有了兩個成員:自己聲明的`APP組件`以及引入的`HttpClientModule`模塊中的`HttpClient`。所以此時在執行`TestBed.createComponent(AppComponent)`當前模塊便擁有了創建`AppComponent`的先決條件。從而使得在動態測試模塊中成功的創建了`AppComponent` 最后我們憂愁單元測試相關注釋內容: ```typescript it('組件初始化', () => { // 創建一個夾具,該夾具中實例化了一個AppComponent對象 const fixture = TestBed.createComponent(AppComponent); // 獲取夾具中的AppComponent對象 const app = fixture.componentInstance; // 預測上述過程沒有發生錯誤,即成功獲取到了AppComponent對象 expect(app).toBeTruthy(); // 啟用angular的自動變更檢測機制,自動對V層中的數據進行渲染 fixture.autoDetectChanges(); ``` # 依賴注入 依賴注入(Dependency Injection)簡稱DI,是大部分框架支持的特性。好像已然成為了面試的必考題了一樣。在此,我們簡單對此有個介紹。 ![](https://img.kancloud.cn/9f/87/9f872b7ab8d76cd32159d6bc49cf8722_475x385.png) 簡單來說:上圖中的????的過程稱即被稱為**依賴注入**。 因為????過程大體實現了:根據AppComponent聲明的**依賴**類型`HttpClient`來將一個`HttpClient`實例**注入**給AppComponent。 更準確的來講,**依賴**一詞源于UML類圖中的類與類的一種關系,表示兩個類之間存在的一種弱關系,是兩個類耦合最小的一種。比如人類當前依賴于手機、依賴于網絡,都是現實生活中的依賴的具體體現。 **注入**一詞就是給的意思,但這個給的操作是Angular主動實施的,是自上而上的,所以稱為**注入**更恰當一些。 # 總結 讓我們簡單總結下: * 組件不能夠獨立存在,其必然屬于某個**模塊** * 一個模塊的**能力**取決于兩個方面: * 其`declarations`的聲明的成員 * 其`imports`中聲明模塊的**可用**成員 * 一個模塊的能力列表決定了其是否有創建某個組件的能力 # 資源列表 | 名稱 | 地址 | |---- | ---- | | Angular模塊簡介 | [https://www.angular.cn/guide/ngmodules](https://www.angular.cn/guide/ngmodules) | | Angular中的依賴注入 | [https://www.angular.cn/guide/dependency-injection](https://www.angular.cn/guide/dependency-injection) | | 本節源碼 | [https://github.com/mengyunzhi/angular11-guild/archive/step2.2.3.zip](https://github.com/mengyunzhi/angular11-guild/archive/step2.2.3.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>

                              哎呀哎呀视频在线观看