Angular2應用的8個主要構造塊

angular 應用:用帶 angular 拓展語法的 HTML 寫模板,用組件類管理這些模板,用服務添加應用邏輯,在模塊中打包發佈組件與服務。通過引導 根模塊啟動應用。 angular 在瀏覽器中接管、展現應用的內容,並根據我們提供的操作指令響應用戶的交互。

這幾個名詞很重要,貫穿angular應用開發。

angular 應用的 8個主要構造塊:

模塊modules 組件components 模板template 元數據metadata 數據綁定data binding 指令directive 服務services 依賴註入dependency injection

模塊

angular 應用是模塊化的,有自己的模塊系統,叫做 angular 模塊/NgModules。

到底模塊是什麼?在angular裡模塊化意味著什麼?

angular 應用至少有一個模塊(根模塊),稱為 AppModule。

大多數應用都有很多其它的 特性模塊,它們由一組領域類、工作流、或緊密相關的功能聚合形成。

angular的所有模塊都是一個帶有 @NgModule 裝飾器的類。

angular的模塊是類!!!

裝飾器是用來修飾JavaScript類的函數。負責把元數據附加到類上。

NgModule 是一個裝飾器函數,它接收一個用來描述模塊屬性的元數據對象。屬性有:

declarations(聲明):本模塊中擁有的視圖類。angular 有三種視圖類:組件、指令、管道。 exports:declarations的子集,可用於其它模塊中的組件模板。 imports:本模塊組件模板中需要由其他模板導出的類。 providers:服務的創建者。本模塊把它們加入全局的服務表中,讓他們在應用中的任何部分都可被訪問到。 bootstrap:標識出應用的主視圖(根組件)。隻有根模塊才可設置此屬性。

下面是一個簡單的根模塊:

// app.module.ts
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

// @NgModle 裝飾器函數,接受一個對象,對象有幾個屬性
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

// AppComponent 的 export 語句導出,根模塊不需要導出,其他組件不需導入根模塊。
export class AppModule { }

引導根模塊來啟動應用。在 main.ts 文件中引導 AppModule:

// app/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
// 從app.module 文件導入瞭 AppModule
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

此時,項目隻有 app/app.module.ts 文件和 app/main.ts ,前者定義瞭應用的根模塊,後者引用它來啟動應用。


Angular 模塊與JavaScript模塊比較:

JavaScript的模塊化是分文件導入的,各文件就是各模塊。

Angular 模塊(用 @NgModule 裝飾的類)是Angular的基礎特性。

JavaScript的模塊系統管理一組JavaScript對象。

在JavaScript中,每個文件就是一個模塊,該文件中定義的對象從屬於該模塊。通過 export 關鍵字,可以把它的某些對象聲明為公開。別的模塊可以使用 import 語句訪問公開對象。

JavaScript的這個特性很有用。

export 關鍵字聲明為公開,import 語句訪問公開對象。

在 Angular 裡這兩種都會用到,從上面的兩個個文件裡,可以看到。


模塊庫

上面所說,Angular 用到瞭 JavaScript模塊,所以它的JS模塊就是庫模塊,JS文件庫。

Angular 庫的名字都以 @angular 前綴,可以使用 npm 包管理工具安裝,並如上面的 import 語句可以訪問它們中的對象。

這點很好理解,Angular 本來就是依托於JS實現的單頁面框架,所以它本身還是需要豐富的JS庫的。

比如,從 @angular/core 庫導入 Component 裝飾器:

import { Component } from '@angular/core';

使用JavaScript導入語句從Angular 庫中導入 Angular 的某些模塊。

import { BrowserModule } from '@angular/platform-browser';

在上面根模塊的代碼中,應用模塊需要 BrowserModule 的某些素材,所以把它加入 @NgModule 元數據的 imports 中:

imports :[ BrowserModule ];

我們看看基本的@angular庫中有哪些JS模塊:

common compiler core forms http platform-browser platform-browser-dynamic router upgrade

所以,我們同時使用 Angular 和 JavaScript的模塊化系統。

這塊的 imports 和 exports 比較混亂,可以自己梳理下。

組件

組件負責控制屏幕上的一小塊地方,就是視圖。

在類中定義組件的應用邏輯(被用來為視圖提供支持)。組件通過一些由屬性和方法組成的API與視圖交互。

所以說組件是聯系視圖的。

前面的 export 關鍵字可以把模塊中的類聲明為公開的,然後 import 裡實現訪問。

類裡面有許多屬性和方法。

模板

通過組件自帶的模板來定義視圖。模板是以HTML形式存在的,它告訴 Angular 如何渲染組件(視圖)。

看一個組件文件的模板:

// app/hero-list.component.html

Hero List

Pick a hero from the list

  • {{hero.name}}

模板看起來就是標準 HTML,它裡面有一些非標準HTML的語法。*ngFor、{{hero.name}}、{click}、[hero] 和 ,它們是 Angular 的模板語法。

所以說,Angular 是通過這種方式來處理 HTML的。

元數據

元數據告訴Angular如何處理一個類。

之前 export 的類裡有一些方法和屬性,但是怎麼處理這個類?

隻要把元數據附加到這個類,就意味著這個類是個組件。

在 TypeScript 中,我們用裝飾器(decorator)來附加元數據。

分析下面的元數據:

// app/hero-list.component.ts
@Component({
  moduleId: module.id,
  selector:    'hero-list',
  templateUrl: 'hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

@Component裝飾器把緊隨其後的類標記成瞭組件類。

在裝飾器後面的類就會被轉為組件類?

裝飾器裡的配置項:

moduleId:為與模塊相關的URL提供基地址。

這個地址怎麼使用的?

selector:CSS 選擇器,它告訴 Angular 在父級HTML尋找一個標簽,然後創建組件實例並插入標簽中。

實現HTML的顯示。

templateUrl:組件HTML模板的模塊相對地址。

HTML模板的設置位置。

providers:數組,包含組件所依賴的服務所需要的依賴註入提供商。告訴Angular該組件的構造函數需要服務,組件可以從服務獲取數據。

某些數據的傳遞通過服務進行,否則,其他的視圖隻能控制靜態的展示。

@Component 裡的元數據會告訴 Angular 如何取得你為組件設定的元數據。

模板、元數據和組件共同描繪出這個視圖。

組件就是視圖,模板提供HTML的結構性。

數據綁定

如果沒有框架,那麼一些都需要我們來做。把數據值推送到HTML控件,並把用戶的反饋接收轉換成動作和值更新顯示,你可以使用jQuery來實現這個過程。

Angular 框架實現數據綁定,一種讓模板各部分與組件的各部分相互聯系的機制。在模板HTML中添加綁定標記,Angular 會連接模板和組件。

意味著,我們刻意自動實現視圖數據的更新,因為它綁定瞭組件,可以實現數據的關聯。

看一個示例:

// app/hero-list.component.ts

  • {{hero.name}}
  •  
  •  

觀察到在這個模板HTML裡,有一些非標準HTML的字符。

{{hero.name}} 插值表達式:在元素中顯示組件的 hero.name屬性的值。
[hero] 屬性綁定:把父組件的值傳到子組件的 hero 屬性中。
(click) 事件綁定:當用戶點擊元素時調用方法。

文件之間的互相關系需要梳理清楚。

雙向數據綁定:同時實現屬性綁定和事件綁定的功能。看示例:

// app/hero-detail.component.ts

數據屬性的值會從具有屬性綁定的組件傳到輸入框,事件綁定使用戶的修改被傳回組件,把屬性值設為最新的值。

指令

Angular 模板是動態的。當 Angular 渲染它們時,它會根據指令對DOM進行修改。

就是說解析模板HTML的時候,會解析其中的指令。

指令是一個帶有指令元數據的類。

指令是一個類,並且它含有指令源數據。

在TypeScript中,要通過 @Directive 裝飾器把元數據附加到類上。

和之前的類的元數據一樣,通過 @Component 裝飾器把元數據附加到後面的類,編程組件類。這個就是通過 @Directive 裝飾器把一些元數據附加到後面的指令類。

結構型指令:通過在DOM中添加、移除、替換元素修改佈局。ngFor 、 ngIf。

屬性指令:修改現有元素的外觀或行為。ngModel

服務

服務分很多種,值、函數、應用所需的特性。

幾乎任何東西都可以是一個服務。典型的服務是一個類。

例如:

日志服務 數據服務 消息總線 稅款計算器 應用程序配置

組件是最大的服務消費者。

組件的一些操作需要服務提供一些數據。

示例,把日志記錄顯示到瀏覽器控制臺:

// app/logger.service.ts

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

這些服務使得組件不用去服務器獲取數據、進行驗證……,這一切都可以通過服務完成。

組件的任務就是提供用戶體驗,僅此而已!

它介於視圖(由模板渲染)和應用邏輯(包括模型)之間。

設計良好的組件為數據綁定提供屬性和方法,對它們不重要的事情委托給服務。

依賴註入

依賴註入是提供類的新實例的一種方式,負責處理好類所需的全部依賴(服務)。

Angular 使用依賴註入提供我們需要的組件及組件所需的服務。

Angular 能通過查看構造函數的參數類型,來的值組件所需的服務。

示例:

// app/hero-list.component.ts

constructor(private service: HeroService) { }

構造函數的參數提到瞭一個服務。

當 Angular 創建組件時,會先為組件所需的服務找一個註入器(Injector)。

註入器是一個維護服務實例的容器,存放著以前創建的實例。如果容器中還沒有所請求的服務實例,註入器就會創建一個服務實例,並且添加到容器中,然後把這個服務返回給 Angular。當所有服務都被解析完並返回, Angular 會以這些服務為參數去調用組件的構造函數,這就是依賴註入。

也就是說服務是先於組件被執行的。它先處理所有的服務到一個倉庫,然後再處理組件,組件需要哪個服務就從倉庫取出來給你。

提供商添加到根模塊,在任何地方使用的都是服務的同一個實例:

// app/app.module.ts

providers: [
  BackendService,
  HeroService,
  Logger
],

提供商是確定處理組件之前必須存在所依賴的組件

也可以把它註冊到組件層:

// app/hero-list.component.ts

@Component({
  moduleId: module.id,
  selector:    'hero-list',
  templateUrl: 'hero-list.component.html',
  providers:  [ HeroService ]
})

添加到裝飾器元數據的屬性中。

依賴註入的要點:

依賴註入滲透在整個Angular框架中 註入器是機制的核心
註入器負責維護一個容器,存放創建過的服務實例 註入器能使用提供商創建一個新的服務實例 提供商是一個用於創建服務的配方。 把提供商註冊到註入器。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *