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

                在前面的章節中,我們已經使用Angular成功的顯示了Hello World!。下面,我們一起探索一下src下的app文件夾。 ``` ├── app │?? ├── app-routing.module.ts ? │?? ├── app.component.html ? ? │?? ├── app.component.sass ? ? │?? ├── app.component.spec.ts ? │?? ├── app.component.ts ? ? │?? └── app.module.ts ? ``` 此文件夾中有6個文件組成,共分成3個大部分。 * ? 路由文件,負責數據轉發。 * ? `app`組件。 * ? 組件視圖(V層)。 * ? 組件樣式(V層)。 * ? `app`組件對應的測試文件。 * ? 組件主體文件(C層)。 * ? `app`模塊,巧的是它的名字與組件重名(僅僅是名字相同而已,就像我們學校有條路起名為逸夫,大家稱它為逸夫路;我還學校有個圖書館,巧的是也叫逸夫,只不過它是逸夫樓一樣)。 他們間大體的關系如下圖示: ![](https://img.kancloud.cn/51/ad/51ad2ef3c040c838356398d93959e4cf_800x166.png) # 模塊 一個angular應用通常會有多個模塊(Module)組成。angular中的模塊共有9個配置部分。其中最常用的有4部分,筆者將其命名為:私有資源列表、公有資源列表、協作模塊列表以及擴展功能列表。 ![](https://img.kancloud.cn/ae/13/ae13e2ea67660d30ab526def84c9575f_572x349.png) 以`app`模塊為例認識下模塊的定義與基本組成: app.module.ts ```typescript import {BrowserModule} from '@angular/platform-browser'; ? import {NgModule} from '@angular/core'; ? import {AppRoutingModule} from './app-routing.module'; ? import {AppComponent} from './app.component'; ? @NgModule({ ? declarations: [ ? AppComponent ? ], imports: [ ? BrowserModule, ? AppRoutingModule, ? ], providers: [], ? bootstrap: [AppComponent] ? }) export class AppModule { ? } ``` * ? 與php中的use, java中的import相同 * ? Angular的注解,將`AppModule`聲明為模塊 * ? 聲明當前模塊中的私有資源列表 * ? 將`app`組件加入到`app`模塊的私有資源列表 * ? 聲明模塊的協作模塊列表 * ? 將瀏覽器模塊加入到協作列表中,該模塊能夠提供的功能是:渲染html文件等。 * ? 將路由模塊加入到協作列表中,該模塊提供的功能由`app-routing.module.ts`中的`AppRouting`模塊所決定。 * ? 擴展功能列表 * ? 啟動組件,由于某些配置的原因,當程序運行時會自動啟動該組件。 * ? 定義類名并使用`export`聲明,表明該類可被`app.module.ts`以外的文件引用。 通過上面的解析可看到,使用`@NgModule`來聲明某類為angular應用中的一個模塊,使用`@NgModule`中配置相應的屬性來對此模塊進行配置。其中屬性`declarations`用于聲明私有資源列表,屬性`imports`用于聲明協作模塊列表,屬性`providers`用于聲明擴展功能列表。 所以模塊的組成也可以使用屬性關鍵字進行如下描述: ![](https://img.kancloud.cn/ca/be/cabe3f0a0b01e0319c843473f0a76a90_566x353.png) ## import與imports ?處的import與?處的imports之間除了長的像以外,本質上并沒有其它的任何關聯。 import是typescript的語法,屬于編程語言層面,表示由某個文件中引入某個類、接口、方法至此文件。與其它語言的命名空間極為類型,稍有不同的是typescript并不需要在文件中使用package或namespace的字樣來規定命名空間,而是將文件的存儲位置直接做為了命名空間來使用。 而imports是屬于angular這個基于typescript開發而來的框架的`@NgModule`注解的一個屬性。它的含意是聲明angular中的模塊引入的其它的模塊。在angular應用中,功能的完成依賴模塊間的協同作業,而imports的作用便是來聲明某個模塊需要的協同者。 # 打開項目 找到前面安裝的WebStorm并運行,選擇open并找到項目文件: ![](https://img.kancloud.cn/40/f0/40f026f51a1bda81329899ea25be84ef_490x310.png) ![](https://img.kancloud.cn/66/a6/66a6ec07ecaabcbe194b758bee80d98f_429x431.png) 稍等片刻,待WebStrom初始化完成。接著打開shell進入項目文件夾,并使用`ng serve --open`啟動項目并自動打開瀏覽器。 # 依賴注入 在Anguar中發起網絡請求需要借助`AppRoutingModule`中被聲明公有資源列表的`HttpClient`。`angular`中的組件可以構造函數中聲明自己所需要的依賴類型。angular在初始化該組件時,將嘗試在組件所在模塊中按構造函數中類型自動注入相關功能的實例。以`App`組件需要具有網絡請求功能的`HttpClient`為例: AppComponent.ts ```typescript import { Component } from '@angular/core'; import {HttpClient} from '@angular/common/http';? @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.sass'] }) export class AppComponent { constructor(private httpClient: HttpClient) { ? console.log(httpClient); } title = 'hello-world'; } ``` ? 使用import由`@angular/common/http`中引入`HttpClient`到此文件。 ? 構造函數中聲明依賴類型為HttpClient。 > 在后續的教程中將只給出文件名,當未對文件路徑做特殊說明時,表示該文件相對于`src/app/`文件夾。比如:`AppComponent.ts`實際為`src/app/AppComponent.ts`。 此時我們刷新頁面查看控制臺,將得到如下錯誤: ![](https://img.kancloud.cn/6d/24/6d24d68fe22a911566f9ac9cb3211e14_772x86.png) 這是由于angular在嘗試注入HttpClient的過程中發生了錯誤。angular能夠成功完成HttpClient的注入,則`App`組件所在的`App`模塊需要滿足以下任一條件: <hr> ???????????????????????????? **以下內容很重要,請牢記!** ???????????????????????????? 1. 在當前模塊**私有資源列表**中能夠找到`HttpClient`。 2. 當前模塊的父模塊的**私有資源列表**中能夠找到`HttpClient`。 3. 在前模塊**協作模塊列表**中的任意模塊的**公有資源列表**中找到`HttpClient` 4. 在前模塊父模塊的**協作模塊列表**中的任意模塊的**公有資源列表**中找到`HttpClient` ???????????????????????????? **以上內容很重要,請牢記!** ???????????????????????????? <hr> 當前`App`模塊可如下可描述為: ![](https://img.kancloud.cn/a8/af/a8af3684a2117184ceaae033756721d6_516x377.png) App模塊在創建AppComponent時,由于在其私有資源中找到了AppComponent,近而進一步為其注入`HttpClient`。在注入`HttpClient`注入未成功進而發生錯誤。 ![](https://img.kancloud.cn/d6/47/d647736feb47feb129927311b54d7cf9_804x374.png) 這當然也在控制臺中報發下錯誤的原因: ``` RROR NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> HttpClient]: StaticInjectorError(Platform: core)[AppComponent -> HttpClient]: NullInjectorError: No provider for HttpClient! ``` > 如果某種錯誤是第一次出現,出現后你完全沒有任何解決它的思路,此時你絕對不應該去傻傻的看代碼是不是哪有問題。你的正確操作應該是:翻譯! ``` 嚴重錯誤 空注入器錯誤:靜態注入器錯誤(AppMoule上發生的[在向AppComponent注入HttpClient時]: 靜態注入器錯誤(在Platform:core上發生的)[在向AppComponent注入HttpClient時]: 空注入器錯誤: 沒有HttpCilent的提供者 ``` 出錯的原因找到了,解決問題的方法也就隨著有了。 ![](https://img.kancloud.cn/39/76/39768a7f8846692d01573d1aacaba85a_808x449.png) >[success] 在angular中,任何模塊都屬于Root模塊的子模塊。 對應代碼如下: app.module.ts ```typescript import {NgModule} from '@angular/core'; import {AppRoutingModule} from './app-routing.module'; import {AppComponent} from './app.component'; import {HttpClientModule} from '@angular/common/http'; ? @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, AppRoutingModule, HttpClientModule ? ], providers: [], bootstrap: [AppComponent] }) export class AppModule { } ``` * ? 由@angular/common/http中引入HttpClientModule至此文件 * ? 在協作模塊列表中加入可以提供`HttpClient`的`HttpClientModule` # 測試 打開控制臺(F12),查看測試消息如下: ![](https://img.kancloud.cn/76/d6/76d62c46f99b434da8905a73689e9581_674x393.png) 控制臺中成功的打印了`HttpClient`對象的信息同時未發生任何錯誤,注入成功。下個小節中展示如何使用`HttpClient`發起網絡請求。 ## 生活與計算機 計算機來源于生活,現實生活中大概會有這樣的場景:技術部門組織春游需要一輛巴士,向公司統一協調部門打電話告知其需求,即:我們需要一輛巴士,此外還需要配備一名司機。 ![](https://img.kancloud.cn/af/e5/afe59c5538178762bb581e55cac6acda_190x115.png) 上面的需求翻譯成代碼語言如下: ``` export class Play { constructor(private bus: Bus, private driver: Driver) } } ``` 其實此時我們并不關心統一協調部門為我們提供的巴士是公司自有車輛還是其由外面租賃的,也不關心巴士的顏色是紅的還是綠的,當然也不關心司機是男是女。我們關心是功能,即巴士有運載人員的功能,司機有駕駛巴士的功能。 統一協調部門得到這個需要以后,去調配巴士和司機,比如此時公司的資源是這樣的: ![](https://img.kancloud.cn/a4/4c/a44cb7581f0f362c8aeb548664dd3581_556x332.png) 統一調度部門發現能夠滿足我們的需求,于是將巴士及能駕駛巴士的司機指派給我們。 ![](https://img.kancloud.cn/04/b5/04b552ae35a1aa08a10f989995d6860b_547x472.png) 要知道并不是所有的公司都有擁有自有用車的,那么當這類公司中的內部部門向統一協調部分發送用車需求時,統一協調部門該怎么辦呢?相信你早有了答案 ---- 找第三租車公司呀! 按上面的思路,假設這個公司的汽車服務需要借肋于租車公司、零食需要借助于超市、藥品需要借助于藥店,那么就會出現如下情況: ![](https://img.kancloud.cn/19/9b/199b63ebdaee93cc83239062e3ca7ecd_814x637.png) 當其它部門提出`汽車+司機+藥品+零食`、`汽車+司機+藥品`、`藥品+零食`需求時,統一協調部門都是可以做到的。但如果有部門提出`飛機+零食`的需求時,統一協調部門就做不到了,此時統一協調部門就會報異常,因為他指不到`飛機`的供應商來滿足其它部門的需求。 >[success] 在計算機的世界里,我們把這種借助統一協調部門來自動提供指定需求的方法稱為**依賴注入 ---- Dependency injection**,也就是你在面試時可能會被問到的`DI`。 ## 計算機與生活 在我們剛剛接觸的Angular的世界里,`app module(模塊)`就是這個公司下的統一協調部門,負責該公司一切資源的調配;`app component組件`則是提出需求的其它部門,提出需求的方法是通過構造函數來聲明。 所以我們前面剛剛添加過的app組件: AppComponet.ts ``` constructor(private httpClient: HttpClient) { ? console.log(httpClient); } ``` ? 找自己所在的module要`HttpClient`。 前面我們分析`AppMoudle`時講過了:`AppComponent`屬于`AppMoudle`。所以這里的`HttpClient`應該由`AppMoudle`來提供,但此時`AppMoudle`還沒有提供`HttpClient`的能力,所以我們打開控制臺后,就出現了: 有了以上的提示再加上我們前面對DI知識的學習,解決這個問題也就不困難了。 # 本節小測 ? 控制臺報錯為: ``` RROR NullInjectorError: StaticInjectorError(AppModule)[AppComponent -> HttpClient]: StaticInjectorError(Platform: core)[AppComponent -> HttpClient]: NullInjectorError: No provider for HttpClient! ``` 報錯內容一直在說`HttpClient`錯誤,而在`AppModule`中卻這樣聲明: ``` imports: [ BrowserModule, AppRoutingModule, HttpClientModule ? ], ``` 問題:為什么提示說缺少HttpClient,但我們卻在此imports了`HttpClientModule`呢?
                  <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>

                              哎呀哎呀视频在线观看