Angular 基礎整理 - 入門
Angular實現語法 typescript
.
Angular基本構造塊是 NgModule
: 會把相關的程式碼收集到一起。Angular應用就是由一組 NgModule
定義出的。應用至少會有一個用於引導應用的跟模組,通常還會有很多特性模組:
- 元件定義檢視
- 檢視是一組課件的螢幕元素,可以根據程式邏輯和資料展示、修改
- 每個應用只收有一個根元件
- 元件使用服務
- 與檢視不相關的業務處理邏輯應該置於服務中
- 服務可以作為依賴被注入到元件中,可以使程式碼更加模組化、增強複用、更加高效
元件和服務本質上都是類,一般使用 裝飾器 來標誌型別
-
元件類的後設資料將元件類和一個用來定義檢視的模板關聯起來。
@Component({ // 後設資料 selector: 'app-base-info', templateUrl: './base-info.component.html', styleUrls: ['./base-info.component.scss'] }) 複製程式碼
- 模板把普通的HTML和Angular 指令 與 繫結標記 組合起來,可以使Angular在呈現HTML之前先修改這些HTML
-
服務類的後設資料提供一些資訊,Angular要用這些資訊讓元件可以通過依賴注入使用該服務
@Injectable({ // 後設資料 providedIn: 'root' }) 複製程式碼
模組
NgModule
為一個元件集宣告瞭編譯的上下文環境,專注於某個應用領域、某個工作流或一組緊密相關的能力。將其中的元件和一組相關程式碼(比如服務)關聯起來,形成功能單元。
每個Angular都有一個跟模組,通常命名為 APPModule
。根模組提供了用來啟動應用的引導機制。
一個應用通常包含很多個功能模組
兩個 NgModule
之間可以相互呼叫功能【被呼叫的功能要提前被匯出】
NgModule
Angular 應用是模組化的,它擁有自己的模組化系統,稱作 NgModule
。 一個 NgModule
就是一個容器,用於存放一些內聚的程式碼塊,這些程式碼塊專注於某個應用領域、某個工作流或一組緊密相關的功能。 它可以包含一些元件、服務提供商或其它程式碼檔案,其作用域由包含它們的 NgModule
定義。 它還可以匯入一些由其它模組中匯出的功能,並匯出一些指定的功能供其它 NgModule
使用。
@NgModule({
providers: Provider[],
/*
在當前模組的注入器中可用的一組可注入物件。
- 在這裡列出了提供商的依賴項可用於注入到任何元件、指令、管道或該注入器下的服務。
- 引導用的 NgModule 使用的是根注入器,可以為應用中的任何部件提供依賴。
*/
declarations: Array<Type<any> | any[]>,
/*
屬於該模組的一組元件、指令和管道(統稱可宣告物件)。
*/
imports: Array<Type<any> | ModuleWithProviders<{}> | any[]>,
/*
這裡列出的 NgModule 所匯出的可宣告物件可用在當前模組內的模板中
*/
exports: Array<Type<any> | any[]>, // 也可匯出其他Module。。。
/*
此 NgModule 中宣告的一組元件、指令和管道可以在匯入了本模組的模組下任何元件的模板中使用。 匯出的這些可宣告物件就是該模組的公共 API。
- 可宣告物件應該且只能屬於一個 NgModule。 一個模組可以列出在它的 exports 中列出一些其它模組,這些模組中所有公開的可宣告物件也同樣會匯出。
- 預設情況下,可宣告物件是私有的。 如果 ModuleA 不匯出 UserComponent,那麼只有這個 ModuleA 中的元件才能使用 UserComponent。
- 匯出具有傳遞性。ModuleA 可以匯入 ModuleB 並將其匯出,這會讓所有 ModuleB 中的匯出同樣可用在匯入了 ModuleA 的那些模組中。
- 根模組沒有任何理由匯出任何東西,因為其它模組永遠不需要匯入根模組。
*/
entryComponents: [], // Module內的公共元件需要在這裡匯出
/*
定義此 NgModule 中要編譯的元件集,這樣它們才可以動態載入到檢視中。
*/
bootstrap: [],
/*
只有根模組才應該設定這個 bootstrap 屬性。
當該模組引導時需要進行引導的元件。列在這裡的所有元件都會自動新增到 entryComponents 中。
*/
schemas: [],
/*
該 NgModule 中允許使用的宣告元素的 schema(HTML 架構)。 元素和屬性(無論是 Angular 元件還是指令)都必須宣告在 schema 中。
*/
id: string,
/*
當前 NgModule 在 getModuleFactory 中的名字或唯一識別符號。 如果為 undefined,則該模組不會被註冊進 getModuleFactory 中。
*/
jit: true
/*
如果為 true,則該模組將會被 AOT 編譯器忽略,因此始終會使用 JIT 編譯。
這是為了支援未來的 Ivy 渲染器,目前沒什麼用。
*/
})
複製程式碼
元件
每個Angular至少有一個元件【根元件】。
每個元件都會定義一個類,包含應用的資料、邏輯、HTML模板
@Component({
selector: 'app-base-info',
templateUrl: './base-info.component.html',
styleUrls: ['./base-info.component.scss']
})
複製程式碼
@Component()
裝飾器表明 緊隨 它的那個類是一個件,並提供模板和該元件專屬的後設資料。
模板、指令和資料繫結
模板灰板HTML和Angular的標記(markup)組合起來,這些標記可以在HTML元素顯示出來之前修改它們。模板中的指令會提供程式邏輯,而繫結標記會把應用中的資料和DOM連線在一起。有兩種型別的資料繫結:
- 事件繫結 讓應用可以通過更新應用的資料來響應目標環境下的使用者輸入
- 屬性繫結 可以將處理過的資料插入到HTML中
模板也可以通過管道轉換要顯示的值以增強使用者體驗【一般用來格式化資料】
模板與檢視
你要通過元件的配套模板來定義其檢視。模板就是一種 HTML,它會告訴 Angular 如何渲染該元件。
檢視通常會分層次進行組織,讓你能以 UI 分割槽或頁面為單位進行修改、顯示或隱藏。 與元件直接關聯的模板會定義該元件的 宿主檢視。該元件還可以定義一個帶層次結構的檢視,它包含一些內嵌的檢視作為其它元件的宿主。
雙向資料繫結
資料繫結標記的四種形式:
{{ value }}
元件 => DOM[property]="value"
元件 => DOM(event)="handler"
DOM => 元件[(ng-mudel)]="property"
元件 <=> DOM
管道
在模板中宣告顯示值的轉換邏輯。帶有 @pipe
裝飾器的類中會定義一個轉換函式,用來把輸入值轉換成供檢視先試用的輸出值。Angular內建管道: Pipes API 列表。
使用方式:{{interpolated_value | pipe_name}}
。
指令
Angular 的模板是 動態的 。當 Angular 渲染它們的時候,會根據 指令 給出的指示對 DOM 進行轉換。 指令就是一個帶有 @Directive()
裝飾器的類。
元件從技術角度上說就是一個指令,但是由於元件對 Angular 應用來說非常獨特、非常重要,因此 Angular 專門定義了 @Component()
裝飾器,它使用一些面向模板的特性擴充套件了 @Directive()
裝飾器。
除元件外,還有兩種指令: 結構型指令 和 屬性型指令。 Angular 本身定義了一系列這兩種型別的指令,你也可以使用 @Directive()
裝飾器來定義自己的指令。
像元件一樣,指令的後設資料把它所裝飾的指令類和一個 selector
關聯起來,selector
用來把該指令插入到 HTML 中。 在模板中,指令通常作為屬性出現在元素標籤上,可能僅僅作為名字出現,也可能作為賦值目標或繫結目標出現。
結構型指令
結構型指令 通過新增、移除或替換DOM元素來修改佈局。
*ngFor
*ngIf
屬性型指令
屬性型指令 會修改現有元素的外觀或行為。
服務與依賴注入
服務
服務 是一個廣義的概念,它包括應用所需的任何值、函式或特性。狹義的服務是一個明確定義了用途的類。它應該做一些具體的事,並做好。與特定檢視無關 、 希望跨元件共享資料、邏輯 情況下可以建立服務類。
理想情況下,元件的工作只管使用者體驗,而不用顧及其它。 它應該提供用於資料繫結的屬性和方法,以便作為檢視(由模板渲染)和應用邏輯(通常包含一些 模型 的概念)的中介者。
服務類的定義通常緊跟在 Injectable()
裝飾器之後。該裝飾器提供的後設資料可以讓服務作為依賴 被注入到 客戶元件中。
對於要用到的任何服務,你必須至少註冊一個提供商。服務可以在自己的後設資料中把自己註冊為提供商,這樣可以讓自己隨處可用。或者,你也可以為特定的模組或元件註冊提供商。要註冊提供商,就要在服務的 @Injectable()
裝飾器中提供它的後設資料,或者在 @NgModule()
或 @Component()
的後設資料中。
預設情況下,Angular CLI 的 ng generate service
命令會在 @Injectable()
裝飾器中提供後設資料來把它註冊到根注入器中。
@Injectable({
providedIn: 'root'
})
複製程式碼
依賴注入
DI 被融入 Angular 框架中,用於在任何地方給新建的元件提供服務或所需的其它東西。 元件是服務的消費者,也就是說,你可以把一個服務注入到元件中,讓元件類得以訪問該服務類。
依賴注入【DI】 可以保持元件類的精簡和高效。有了DI,元件就不用從伺服器獲取資料、驗證使用者輸入或直接把日誌寫到控制檯,而是把這些任務委託給服務。
路由
Angular 的 Router
模組提供了一個服務,它可以讓你定義在應用的各個不同狀態和檢視層次結構之間導航時要使用的路徑。 它的工作模型基於人們熟知的瀏覽器導航約定:
- 在位址列輸入 URL,瀏覽器就會導航到相應的頁面。
- 在頁面中點選連結,瀏覽器就會導航到一個新頁面。
- 點選瀏覽器的前進和後退按鈕,瀏覽器就會在你的瀏覽歷史中向前或向後導航。
不過路由器會把類似 URL 的路徑對映到檢視而不是頁面。 當使用者執行一個動作時(比如點選連結),本應該在瀏覽器中載入一個新頁面,但是路由器攔截了瀏覽器的這個行為,並顯示或隱藏一個檢視層次結構。
如果路由器認為當前的應用狀態需要某些特定的功能,而定義此功能的模組尚未載入,路由器就會按需 惰性載入 此模組。
元件、檢視、服務
生命週期
每個元件都有一個被Angular管理的生命週期。
元件生命週期
指令和元件的例項有一個生命週期:當Angular新建、更新和銷燬它們時觸發。通過實現一個或多個Angular Core 庫裡定義的 生命週期鉤子 介面,我們可以在特定時期執行特定方法。
生命週期順序
當 Angular 使用建構函式新建一個元件或指令後,就會按下面的順序在特定時刻呼叫這些生命週期鉤子方法:
鉤子 | 用途及時機 |
---|---|
ngOnChanges() |
當 Angular(重新)設定資料繫結輸入屬性時響應。 該方法接受當前和上一屬性值的 SimpleChanges 物件在 ngOnInit() 之前以及所繫結的一個或多個輸入屬性的值發生變化時都會呼叫。 |
ngOnInit() |
在 Angular 第一次顯示資料繫結和設定指令/元件的輸入屬性之後,初始化指令/元件。在第一輪 ngOnChanges() 完成之後呼叫,只呼叫一次。 |
ngDoCheck() |
檢測,並在發生 Angular 無法或不願意自己檢測的變化時作出反應。在每個變更檢測週期中,緊跟在 ngOnChanges() 和 ngOnInit() 後面呼叫。 |
ngAfterContentInit() |
沒當 Angular 把外部內容投影進元件/指令的檢視之後呼叫。第一次 ngDoCheck() 之後呼叫,只呼叫一次。 |
ngAfterContentChecked() |
每當 Angular 完成被投影元件內容的變更檢測之後呼叫。ngAfterContentInit() 和每次 ngDoCheck() 之後呼叫 |
ngAfterViewInit() |
每當 Angular 初始化完元件檢視及其子檢視之後呼叫。第一次 ngAfterContentChecked() 之後呼叫,只呼叫一次。 |
ngAfterViewChecked() |
每當 Angular 做完元件檢視和子檢視的變更檢測之後呼叫。ngAfterViewInit() 和每次 ngAfterContentChecked() 之後呼叫。 |
ngOnDestroy() |
沒當 Angular 每次銷燬指令/元件之前呼叫並清掃。 在這兒反訂閱可觀察物件和分離事件處理器,以防記憶體洩漏。在 Angular 銷燬指令/元件之前呼叫。 |