如何簡單地介紹angular框架(基礎概念篇)

爲什麼寫這篇文章:

使用angular開發也有快2年的時間,突然有一天有人問我,你能不能給我簡單講一下angular框架?雖然每天都在使用,卻不知如何表述,故決定寫這樣一篇文章。

一句話知識點:

Angular本身就是用 TypeScript 寫成的,核心功能和可選功能作爲一組 TypeScript庫,根據需要導入到應用中;

Angular 的基本構建塊是 NgModule特性模塊,爲組件提供編譯的上下文環境。Angular應用就是由一組NgModule定義的, NgModule 可以將其組件和一組相關代碼(如服務)關聯起來,形成功能單元;

組件定義視圖,由html模板+css樣式+ts組件類構成,也可以根據需要引入服務類。

模板把傳統的html和angular模板語法結合起來,是HTML的升級版(插值,屬性綁定,雙向數據綁定,事件綁定,指令,結構指令,屬性指令,管道等等);

css樣式可以使用scss和less進行預擴展;

組件類定義應用的數據和業務邏輯;

組件可以把服務類通過DI依賴注入到組件中;

通過Router服務在多個視圖之間進行導航功能;

不過路由器會把類似 URL 的路徑映射到視圖而不是頁面。 當用戶執行一個動作時(比如點擊鏈接),本應該在瀏覽器中加載一個新頁面,但是路由器攔截了瀏覽器的這個行爲,並顯示或隱藏一個視圖層次結構;

如果路由器認爲當前的應用狀態需要某些特定的功能,而定義此功能的模塊尚未加載,路由器就會按需惰性加載此模塊

導航路徑和你的組件關聯起來。 路徑(path)使用類似 URL 的語法來和程序數據整合在一起,就像模板語法會把你的視圖和程序數據整合起來一樣。 然後你就可以用程序邏輯來決定要顯示或隱藏哪些視圖,以根據你制定的訪問規則對用戶的輸入做出響應;

裝飾器類型:

@Component()

@Injectable()

以上是視圖的構成:

組件和模板共同構成了視圖:

  1. 組件類上的裝飾器@Component()爲其添加元數據,包括指向對應模板的指針;
  2. 模板中的指令和綁定標記會根據程序數據和邏輯修改這些視圖;
  3. DI依賴注入器會爲組件提供特定的服務,如路由器服務,提供視圖之前的導航,網絡服務,與服務器的I/O數據交互。

NgModule簡介

它就是一個容器,存放一些內聚的代碼塊,使用某個特定的功能。它可以包含組件,服務提供商,其他代碼文件等。

@NgModule函數的入參:

declarations(可聲明對象表) —— 那些屬於本 NgModule 的組件、指令、管道。

exports(導出表) —— 那些能在其它模塊的組件模板中使用的可聲明對象的子集。

imports(導入表) —— 那些導出了本模塊中的組件模板所需的類的其它模塊。

Providers(服務提供商) —— 本模塊向全局服務中貢獻的那些服務的創建器。 這些服務能被本應用中的任何部分使用。(你也可以在組件級別指定服務提供商,這通常是首選方式。)

Bootstrap(啓動項) —— 應用的主視圖,稱爲根組件。它是應用中所有其它視圖的宿主。只有根模塊才應該設置這個 bootstrap 屬性;

 

NgModule和組件:

NgModule可以declaration任意數量的其他組件,這些組件可以是通過路由加載,或者是通過模板創建,他們都屬於這個NgModule的組件會共享同一個編譯上下文環境,即爲,imports的模塊(服務類,框架的模塊)都可以在組件中使用

組件還可以包含視圖層次結構。一個視圖層次結構可以混合使用由不同NgModule中的組件定義的視圖,比如UI庫。宿主視圖爲起點,下面包含內嵌視圖

 

Component簡介

組件構成視圖的一部分。在組件類彙總定義它的應用邏輯,通過定義屬性和方法組成的API與視圖交互

組件可以通過TS的構造器參數性屬性,通過依賴注入系統將服務提供給該組件。

組件都有生命週期鉤子(lifecycle hooks),因爲ng會在應用的過程中,對組件進行create、update、destroy操作,故可以根據需要在對應的鉤子環節添加額外的應用邏輯。

組件的元數據:

@Component裝飾器後面緊跟的類就代表一個組件類(類似於JAVA的註解),併爲其制定metadata元數據,即爲函數的入參

元數據告訴angular到哪裏獲取它的主要構造塊,來創建和展示這個組件及其視圖。具體來說,它把模板和該組件關聯起來,該組件及其模板,共同描述一個視圖

具體配置項如下:

selector:是一個 CSS 選擇器,它會告訴 Angular,一旦在模板 HTML 中找到了這個選擇器對應的標籤,就創建並插入該組件的一個實例的視圖。

templateUrl:該組件的 HTML 模板文件相對於這個組件文件的地址。 另外,你還可以用 template 屬性的值來提供內聯的 HTML 模板。 這個模板定義了該組件的宿主視圖

providers:當前組件所需的服務提供商的一個數組。

 

模板與視圖

與組件直接關聯的模板就叫宿主視圖,該組件還可以定義一個帶層次結構的視圖,在模板裏引入其他組件關聯的模板(可以是任何模塊中定義的組件),他們就叫內嵌視圖。

模板語法

傳統HTML與angular模板語法結合,他可以使用數據綁定來協調應用和DOM中的數據,使用Pipes管道對數據進行轉換,使用Directives指令在內容上添加邏輯代碼。

數據綁定

數據綁定標記有四種形式,每種形式有方向性的,如下圖:

 

雙向數據綁定主要用於模板驅動表單,在Form元素中使用,代指起value屬性(語法糖:將屬性綁定和事件綁定合作成一種獨特的寫法)。

 

父子直接通信原理,如下圖:

 

管道

@Pipe()

作用在模板中聲明的顯示值,做一個對應的轉換的一個轉換函數。

使用時,使用管道操作符 |

 

指令

@Directive()

理論上,組件就是一個指令。

Angular的模板是動態的,只有當渲染他們的時候解析,根據指令給出的指示對DOM進行轉換。

分類:結構指令 / 屬性指令.

結構指令:通過添加,移除,替換DOM元素來修改佈局。

屬性指令:修改元素的外觀或行爲。

 

服務與DI

@Injectable()

組件僅僅提供用於視圖模板中數據綁定的屬性和方法,讓組件更加精簡和高效。

可以將諸如從服務器上獲取數據,驗證用戶輸入等委託給各種服務,提高模塊化和複用性。

 

依賴注入

 

組件是服務的消費者。

機制:

注入器injector:在ng啓動過程中會自動創建全應用級注入器;

注入器會創建依賴,通過維護一個容器來管理這些依賴,複用;

提供商provider:告訴注入器如何創建或獲取依賴,即爲新實例。

 

提供服務

服務可以在自己的metadata元數據中註冊爲提供商;

爲特定的模板或組件註冊提供商,在@NgModule()或@Component()元數據中提供;

示例:

 

 

方式一:類本身上創建一個單一的共享實例,任何類中都可以直接調用;

這種方式可以讓可以讓ng通過移除那些未被使用過的服務來優化大小;

 

方式二:在模塊中創建服務商,該服務的作用範圍僅在該NgModule中的所有組件可用;

 

方式三:在組件註冊provider,爲該組件的每一個新實例提供該服務的一個新實例;

 

通過 interface 創建模型類,作爲某個組件類的屬性的類型(TS的類型檢查);

 

基礎常識:

  1. ngModel依賴FormsModule模塊;
  2. 組件必須聲明且只能聲明(declarations)在一個NgModule中;
  3. 使用CLI創建組件會自動把它添加到NgModule中,如果手動創建組件,那還需要在對應的模塊中聲明一次;
  4. 如果不同模塊需要聲明同一個組件,可以將這種組件聲明到一個公共的模塊裏面,然後分開在其他需要的模塊引入該公共模塊,再添加到imports數組中;另外,特別注意,公共慕課必須把組件export出去;
  5. @Input()裝飾器代表的是一個輸入屬性;

父子通信:

[hero]="selectedHero" 是 Angular 的屬性綁定語法;

這是一種單向數據綁定。從 父組件的 selectedHero 屬性綁定到目標元素的 hero 屬性,並映射到了子組件的 hero 屬性;

 

爲什麼需要服務

因爲組件的職責是聚焦於展示數據,處理與視圖的數據交互,而不關心如何獲取或保存數據,把這個工作的職責委託給某個服務;

服務可以在多個「相互不知道」的類之間共享信息;

服務提供商provider:某種可以創建或交付一個服務的東西;

組件的構造函數的參數:

  1. 聲明一個私有屬性;
  2. 把它標記爲一個服務的注入點;
  3. HttpClient調用方法時,可以更加明確定義返回的類型;

特別注意:

  1. 某個服務類裏暴露一個屬性作爲一個數據緩存,那麼在組件的模板裏使用時,必須在注入該服務時,使用public關鍵字,因爲Angular只會綁定到組件的公共屬性;

服務的一個基本流程:

  1. 創建一個服務類;
  2. 根注入器中註冊爲該服務的提供商 / NgModule / Component 註冊服務提供商;
  3. 通過DI機制把它注入到組件中;
  4. Angular在創建組件時,就會爲該組件創建該服務的一個單例實例;
  5. (服務可以注入其他服務,特別注意各個服務提供商的註冊引起的問題;)

Router基礎開發

  1. 引入依賴router庫的RouterModule和Routes模塊;
  2. 根模塊元數據初始化路由器時,在imports中,使用RouterModule.forRoot(),創建路由所需的服務提供商和指令,然後纔開始監聽瀏覽器地址的變化,子路由使用.forChild();
  3. 在exports中,導出RouterModule的目的,以便於它在整個應用程序中生效;
  4. 在該模板的根組件的模板中,添加RouterOutlet路由出口;
  5. 模板中導航:a標籤上使用routerLink(它是RouterLink指令的選擇器);

{ path: 'detail/:id', component: HeroDetailComponent }

path路徑中的冒號 ( : )表示:某個名稱是一個佔位符,可以在路由參數中獲取;

 

拿路由參數:

  1. 引入ActivatedRoute模塊,它保存着組件實例的路由信息,可以拿到id屬性;
  2. 通過this.route.snapshot.paramMap.get(‘id’)拿到id值,其中,paramMap是一個從URL中提權的路由參數值的字典;
  3. 反引號(`)定義模板字符串字面量;
  4. Location模塊,與瀏覽器打交道的,控制瀏覽器的前進後退操作,例如,this.loaction.back() ;

 

HTTP基礎應用

 

HttpClient是Angular通過HTTP與遠程服務器通訊的重要機制;

在根模塊中導入HttpClientModule模塊;

 

HttpClient的Observable總是發出一個值,然後complete,不會再發出其他值;

內部捕獲錯誤,pipe中的catchError攔截失敗的observable,可以定義一個方法來返回安全值,讓應用繼續正常運行;

 

AsyncPipe管道

<li *ngFor="let hero of heroes$ | async" >

 

Heroes$中,$是一個約定,表示它是一個Observable;

在模板中可以使用async管道,自動訂閱Observable,就不必在組件類中subscribe;

 

Rxjs的各種操作符(核心庫)

通過Observable來編寫異步和基於事件的庫;

基本概念:

  1. Observable (可觀察對象):表示一個概念,這個概念是一個可調用的未來值或事件的集合;
  2. Observer (觀察者):一個回調函數的集合,它知道如何去監聽由 Observable 提供的值;
  3. Subscription (訂閱):表示 Observable 的執行,主要用於取消 Observable 的執行;
  4. Operators (操作符): 採用函數式編程風格的純函數 (pure function),使用像 map、filter、concat、flatMap 等這樣的操作符來處理集合;
  5. Subject (主體): 相當於 EventEmitter,並且是將值或事件多路推送給多個 Observer 的唯一方式;
  6. Schedulers(調度器):用來控制併發並且是中央集權的調度員,允許我們在發生計算時進行協調,例如 setTimeout 或 requestAnimationFrame 或其他。

學習Rx,主要就是學習各種操作符,這裏就不展開介紹。

總結:

以上就是Angular框架的整體介紹,掌握了它的基本運行原理。不僅會用,還能很好的表達出來。