天天看點

angular架構預覽(子產品,元件.資料綁定等)

概念來自Angular官網

Angular 是一個用 HTML 和 JavaScript 或者一個可以編譯成 JavaScript 的語言(例如 Dart 或者 TypeScript ),來建構用戶端應用的架構。

寫Angualr應用的步驟

        a.用 Angular 擴充文法編寫 HTML 模闆              template

        b. 用元件類管理這些模闆                                    component

        c.用服務添加應用邏輯                                         service

        d.用子產品打包釋出元件與服務。                            ng bulid

        e.通過引導根子產品來啟動該應用。                        ng server 

     Angular 在浏覽器中接管、展現應用的内容,并根據我們提供的操作指令響應使用者的互動

       圖檔示意:   

angular架構預覽(子產品,元件.資料綁定等)

一:子產品(Module)

                    Angular 應用是子產品化的,并且 Angular 有自己的子產品系統,它被稱為 Angular 子產品或 NgModules。

                    Angular 子產品"很重要"。

        根子產品在一些小型應用中可能是唯一的子產品,大多數應用會有很多特性子產品,每個子產品都是一個内聚的代碼塊專注于某個應用領域、工作流或緊密相關的功能。

        Angular 子產品(無論是根子產品還是特性子產品)都是一個帶有"<code>@NgModule"</code>裝飾器的類。

                裝飾器是用來修飾 JavaScript 類的函數。 Angular 有很多裝飾器,它們負責把“”中繼資料"附加到類上,以了解那些類的"設計意圖"以及它們應"如何工作"。

<code>declarations</code> - 聲明本子產品中擁有的視圖類。Angular 有三種視圖類:元件、指令和管道。       component

<code>exports</code> - declarations 的子集,可用于其它子產品的元件模版。                                                                                    

<code>imports</code> - 本子產品聲明的元件模闆需要的類所在的其它子產品。                                                module

<code>providers</code> - 服務的建立者,并加入到全局服務清單中,可用于應用任何部分。                      service

<code>bootstrap</code> - 指定應用的主視圖(稱為--根元件---),它是所有其它視圖的--宿主--。隻有----根子產品---才能設定<code>bootstrap</code>屬性。  

一個簡單的跟子產品 

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

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

import {AppRoutingModule} from './app.routing';

import {heroService} from './data/hero.service';

import { AppComponent } from './app.component';

@NgModule({

  declarations: [

    AppComponent,

    heroListComponent,

    heroDetailComponent

  ],

  imports: [

    BrowserModule,

    AppRoutingModule

  providers: [heroService],

  bootstrap: [AppComponent],

  exports:[AppComponent]

})

export class AppModule { }

<code>AppComponent</code>的<code>export</code>語句隻是用于示範如何導出的,它在這個例子中并不是必須的。根子產品不需要導出任何東西,因為其它元件不需要導入"根子產品"。

我們通過引導根子產品來啟動應用。 在開發期間,你通常在一個<code>main.ts</code>檔案中引導<code>AppModule</code>,就像這樣:

            .src/main.ts

    import { AppModule } from './app/app.module';

    platformBrowserDynamic().bootstrapModule(AppModule);

NgModule(一個帶<code>@NgModule</code>裝飾器的類)是 Angular 的基礎特性之一。

JavaScript 也有自己的子產品系統,用來管理一組 JavaScript 對象。 它與 Angular 的子產品系統完全不同且完全無關。

JavaScript 中,每個檔案是一個子產品,檔案中定義的所有對象都從屬于那個子產品。 通過<code>export</code>關鍵字,子產品可以把它的某些對象聲明為公共的。 其它 JavaScript 子產品可以使用import 語句來通路這些公共對象。

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

    import { AppComponent } from './app.component';

    export class AppModule { }

這兩個子產品化系統是互補的,我們在寫程式時都會用到。

二:元件(component)

    元件負責控制螢幕上的一小塊區域,我們稱之為視圖。

        我們在類中定義元件的應用邏輯,為視圖提供支援。 元件通過一些由屬性和方法組成的 API 與視圖互動。

例如,<code>GenrealListCompoent</code>有一個<code>Genreals</code>屬性,它傳回一個英雄數組,這個數組從一個服務獲得。 <code>GenrealListCompoent</code>還有一個<code>selectedGenreal()</code>方法,當使用者從清單中點選一個英雄時,就把它/她設定到<code>selectedGenreal</code>屬性。

export class GenrealListCompoent implements OnInit {

 genreals: Genreal[];

 selectedGenreal: Genreal;

 constructor(private service: HeroService) { }

 ngOnInit() {

   this.genreals= this.service.getGenreals();

 }

 selectHero(genreal: Genreal) { this.selectedGenreal= genreal; }}

當使用者在這個應用中漫遊時, Angular 會建立、更新和銷毀元件。 應用可以通過生命周期鈎子在元件生命周期的各個時間點上插入自己的操作,例如上面聲明的<code>ngOnInit()</code>。

三:模版(template)

    我們通過元件的自帶的模闆來定義元件視圖。模闆以 HTML 形式存在,告訴 Angular 如何渲染元件。

    多數情況下,模闆看起來很像标準 HTML,當然也有一點不同的地方。下面是<code>GenrealListCompoent</code>元件的一個模闆

&lt;div class="container"&gt;

&lt;div class="row"&gt;

&lt;h1&gt;`title`&lt;/h1&gt;

&lt;/div&gt;

&lt;ul class="controller"&gt;

&lt;!-- 當表達式(hero === selectedHero)為true時,Angular會添加一個CSS類selected。為false時則會移除selected類。 --&gt;

&lt;li *ngFor="let item of generals" (click)="oSelect(item)" [class.selected]="item==selectGeneral"&gt;

&lt;label class="col-lg-4"&gt;`item`.`id` &lt;/label&gt; 

&lt;span class="col-lg-4"&gt;

`item`.`name`

&lt;/span&gt;

 `item`.`source`

&lt;/li&gt;

&lt;/ul&gt;

&lt;general-detail [general]='selectGeneral'&gt;&lt;/general-detail&gt;

模闆除了可以使用像<code>&lt;h2&gt;</code>和<code>&lt;p&gt;</code>這樣的典型的 HTML 元素,還能使用其它元素。 例如,像<code>*ngFor</code>、<code>{{item.name}}</code>、<code>(click)</code>、<code>[general]</code>和<code>&lt;general-detail&gt;</code>這樣的代碼使用了 Angular 的模版文法。

在模闆的最後一行,<code>&lt;general-detail&gt;</code>标簽就是一個用來表示新元件<code>GenrealListCompoent</code>的自定義元素。

    圖檔示意:

angular架構預覽(子產品,元件.資料綁定等)

四:中繼資料(Metadata)

        作用:中繼資料告訴 Angular 如何處理一個類。

<code>回頭看看</code><code>GenrealListCompoent</code>就會明白:它隻是一個類。 一點架構的痕迹也沒有,裡面完全沒有出現 "Angular" 的字樣。

        實際上,<code>GenrealListCompoent</code>真的隻是一個類。直到我們"告訴 Angular 它是一個元件"。

        要告訴 Angular <code>GenrealListCompoent</code>是個元件,隻要把中繼資料附加到這個類。

在TypeScript中,我們用裝飾器 (decorator) 來附加中繼資料

下面就是<code>GenrealListCompoent</code>的一些中繼資料。

@Component({

 selector:    'genreal-list',

 templateUrl: './hero-list.component.html',

 providers:  [ GenrealService ]})export class GenrealListCompoent implements OnInit {/* . . . */}這裡看到<code>@Component</code>裝飾器,它把緊随其後的類标記成了元件類。

<code>@Component</code>裝飾器能接受一個配置對象, Angular 會基于這些資訊建立和展示元件及其視圖。

<code>@Component</code>的配置項包括:

<code>selector</code>: CSS 選擇器,它告訴 Angular 在父級 HTML 中查找<code>&lt;hero-list&gt;</code>标簽,建立并插入該元件。 例如,如果應用的 HTML 包含<code>&lt;hero-list&gt;&lt;/hero-list&gt;</code>, Angular 就會把<code>HeroListComponent</code>的一個執行個體插入到這個标簽中。

<code>templateUrl</code>:元件 HTML 模闆的子產品相對位址

template:模版-----&gt;template:``,

 styleUrls:元件HTML模版的樣式的相對位址

<code>providers</code> - 元件所需服務的依賴注入提供商數組。 這是在告訴 Angular:該元件的構造函數需要一個<code>GenrealService</code>服務,這樣元件就可以從"服務"中獲得英雄"資料"。

angular架構預覽(子產品,元件.資料綁定等)

<code>@Component</code>裡面的中繼資料會告訴 Angular 從哪裡擷取你為元件指定的主要的建構塊。

模闆、中繼資料群組件共同描繪出這個視圖。

Apply other metadata decorators in a similar fashion to guide Angular behavior. <code>@Injectable</code>, <code>@Input</code>, and <code>@Output</code> are a few of the more popular decorators.其它中繼資料裝飾器用類似的方式來指導 Angular 的行為。 例如<code>@Injectable</code>、<code>@Input</code>和<code>@Output</code>等是一些最常用的裝飾器。

這種架構處理方式是:你向代碼中添加中繼資料,以便 Angular 知道該怎麼做。

五:資料綁定(Data binding)

                    如果沒有架構,我們就得自己把資料值推送到 HTML 控件中,并把使用者的回報轉換成動作和值更新。 如果手工寫代碼來實作這些推/拉邏輯,肯定會枯燥乏味、容易出錯,讀起來簡直是噩夢 —— 寫過 jQuery 的程式員大概都對此深有體會。

angular架構預覽(子產品,元件.資料綁定等)

Angular 支援資料綁定,一種讓模闆的各部分與元件的各部分互相合作的機制。 我們往模闆 HTML 中添加綁定标記,來告訴 Angular 如何把二者聯系起來。

As the diagram shows, there are four forms of data binding syntax. Each form has a direction — to the DOM, from the DOM, or in both directions.如圖所示,

資料綁定的文法有四種形式。每種形式都有一個方向 —— 綁定到 DOM 、綁定自 DOM 以及雙向綁定。

<code></code>

    &lt;li&gt;`hero`.`name`&lt;/li&gt;

    &lt;hero-detail [hero]="selectedHero"&gt;

    &lt;/hero-detail&gt;&lt;li (click)="selectHero(hero)"&gt;&lt;/li&gt;

<code>`hero`.`name`</code>插值表達式在    <code>&lt;li&gt;</code>标簽中顯示元件的<code>hero.name</code>屬性的值。--------&gt;component.ts  中   hero={name:'angular'};

<code>[hero]</code>屬性綁定    把父元件<code>HeroListComponent</code>的<code>selectedHero</code>的值傳到子元件<code>HeroDetailComponent</code>的<code>hero</code>屬性中。父元件向子元件傳遞值

<code>(click)</code> 事件綁定    在使用者點選英雄的名字時調用元件的<code>selectHero</code>方法。                事件觸發後調用component中的方法。

        雙向資料綁定是"重要"的第四種綁定形式,它使用<code>ngModel</code>指令組合了屬性綁定和事件綁定的功能。

示例:

    &lt;input [(ngModel)]="hero.name"&gt;

在雙向綁定中,資料屬性值通過 '屬性綁定' 從 元件 流到 輸入框 。使用者的修改通過 '事件綁定' 流回 元件 ,把 屬性值 設定為 最新的值 。

Angular 在每個 JavaScript 事件循環中處理所有的資料綁定,它會從元件樹的 根部 開始,遞歸 處理全部子元件。

angular架構預覽(子產品,元件.資料綁定等)

資料綁定在模闆與對應元件的互動中扮演了重要的角色。 

angular架構預覽(子產品,元件.資料綁定等)

資料綁定在父元件與子元件的通訊中也同樣重要。

六:指令 (directive)

angular架構預覽(子產品,元件.資料綁定等)

Angular 模闆是動态的。當 Angular 渲染它們時,它會根據指令提供的操作對 DOM 進行轉換。

元件是一個帶模闆的指令;<code>@Component</code>裝飾器實際上就是一個<code>@Directive</code>裝飾器,隻是擴充了一些面向模闆的特性。

結構型指令和屬性 (attribute) 型指令。

它們往往像屬性 (attribute) 一樣出現在元素标簽中, 偶爾會以名字的形式出現,但多數時候還是作為指派目标或綁定目标出現。

結構型指令通過在 DOM 中添加、移除和替換元素來修改布局。

例:

    &lt;li *ngFor="let hero of heroes"&gt;&lt;/li&gt;

 &lt;hero-detail *ngIf="selectedHero"&gt;&lt;/hero-detail&gt;

屬性型 指令修改一個現有元素的外觀或行為

<code>ngModel</code>指令就是屬性型指令的一個例子,它實作了雙向資料綁定。 <code>ngModel</code>修改現有元素(一般是<code>&lt;input&gt;</code>)的行為:設定其顯示屬性值,并響應 change 事件。

&lt;input [(ngModel)]="hero.name"&gt;

七:服務 (services) 類似于java中的service層

服務是一個廣義範疇,包括:值、函數,或應用所需的特性。

幾乎任何東西都可以是一個服務。 典型的服務是一個類,具有‘’專注的‘’、‘’明确的‘’用途。它應該做一件‘’特定‘’的事情,并把它‘’做好‘’。

服務沒有什麼特别屬于 Angular 的特性。 Angular 對于服務也沒有什麼定義。 它甚至都沒有定義服務的基類,也沒有地方注冊一個服務。

即便如此,服務仍然是任何 Angular 應用的基礎。元件就是最大的服務消費者。

下面是一個服務類的範例,用于把日志記錄到浏覽器的控制台

export class Logger {

 log(msg: any)   { console.log(msg); }

 error(msg: any) { console.error(msg); }

 warn(msg: any)  { console.warn(msg); }}

export class HeroService {

 private heroes: Hero[] = [];

 constructor(

   private backend: BackendService,

   private logger: Logger) { }

 getHeroes() {

   this.backend.getAll(Hero).then( (heroes: Hero[]) =&gt; {

     this.logger.log(`Fetched ${heroes.length} heroes.`);

     this.heroes.push(...heroes); // fill cache

   });

   return this.heroes;

 }}

服務無處不在。

      元件類應保持精簡。"元件本身"不從伺服器獲得資料、不進行驗證輸入,也不直接往控制台寫日志。 它們把這些任務委托給"服務"。

     元件的任務就是提供使用者體驗,僅此而已。它介于視圖(由模闆渲染)和應用邏輯(通常包括模型的某些概念)之間。 設計良好的元件為資料綁定提供屬性和方法,把其它瑣事都委托給服務。

    Angular 不會強制要求我們遵循這些原則。

    Angular 幫助我們遵循這些原則 —— 它讓我們能輕易地把應用邏輯拆分到服務,并通過依賴注入來在元件中使用這些服務。

八:依賴注入(Dependency injection) 

        依賴注入”是提供'類的新執行個體'的一種方式,還負責'處理'好類所需的'全部依賴'。大多數'依賴'都是服務。 Angular 使用依賴注入來提供新元件以及元件所需的服務。

Angular 通過檢視構造函數的參數類型得知元件需要哪些服務。

 例如,<code>HeroListComponent</code>元件的構造函數需要一個<code>HeroService</code>服務:

        constructor(private service: HeroService) { }

當 Angular 建立元件時,會首先為元件所需的服務請求一個注入器 (injector)。

注入器維護了一個服務執行個體的容器,存放着以前建立的執行個體。 如果所請求的服務執行個體不在容器中,注入器就會建立一個服務執行個體,并且添加到容器中,然後把這個服務傳回給 Angular。 當所有請求的服務都被解析完并傳回時,Angular 會以這些服務為參數去調用元件的構造函數。 這就是依賴注入 。

如果注入器還沒有<code>HeroService</code>,它怎麼知道該如何建立一個呢?

簡單點說,我們必須先用注入器(injector)為<code>HeroService</code>注冊一個提供商(provider)。 提供商用來建立或傳回服務,通常就是這個服務類本身(相當于<code>new HeroService()</code>)。

我們可以在子產品中或元件中注冊提供商。

但通常會把提供商添加到根子產品上,以便在任何地方都使用服務的同一個執行個體。

providers: [

 BackendService,

 HeroService,

 Logger],

需要記住的關于依賴注入的要點是:

依賴注入滲透在整個 Angular 架構中,被到處使用。

注入器 (injector) 是本機制的核心。

注入器負責維護一個容器,用于存放它建立過的服務執行個體。

注入器能使用提供商建立一個新的服務執行個體。

提供商是一個用于建立服務的配方。

把提供商注冊到注入器。

本文轉自 沉迷學習中 51CTO部落格,原文連結:http://blog.51cto.com/12907581/1965575,如需轉載請自行聯系原作者

繼續閱讀