我們今天要學習的是Angular2的模塊系統,一般情況下我們使用一個根模塊去啟動我們的應用,然后使用許多的功能模塊去豐富我們的應用,擴展我們應用的功能.這些全部依靠我們的 NgModule
裝飾器,接下來我們就來好好學習一下這個裝飾器.當然在這個過程中你會遇到一些新的指令,概念等等;但是別慌,我們會在以后的文章中一個一個的詳細講解呢.
在開始今天的練習之前,我們首先來熟悉一下 NgModule
的API,
interface NgModule {
// providers: 這個選項是一個數組,需要我們列出我們這個模塊的一些需要共用的服務 // 然后我們就可以在這個模塊的各個組件中通過依賴注入使用了. providers : Provider[] // declarations: 數組類型的選項, 用來聲明屬於這個模塊的指令,管道等等. // 然后我們就可以在這個模塊中使用它們了. declarations : Array<Type<any>|any[]> // imports: 數組類型的選項,我們的模塊需要依賴的一些其他的模塊,這樣做的目的使我們這個模塊 // 可以直接使用別的模塊提供的一些指令,組件等等. imports : Array<Type<any>|ModuleWithProviders|any[]> // exports: 數組類型的選項,我們這個模塊需要導出的一些組件,指令,模塊等; // 如果別的模塊導入了我們這個模塊, // 那么別的模塊就可以直接使用我們在這里導出的組件,指令模塊等. exports : Array<Type<any>|any[]> // entryComponents: 數組類型的選項,指定一系列的組件,這些組件將會在這個模塊定義的時候進行編譯 // Angular會為每一個組件創建一個ComponentFactory然后把它存儲在ComponentFactoryResolver entryComponents : Array<Type<any>|any[]> // bootstrap: 數組類型選項, 指定了這個模塊啟動的時候應該啟動的組件.當然這些組件會被自動的加入到entryComponents中去 bootstrap : Array<Type<any>|any[]> // schemas: 不屬於Angular的組件或者指令的元素或者屬性都需要在這里進行聲明. schemas : Array<SchemaMetadata|any[]> // id: 字符串類型的選項,模塊的隱藏ID,它可以是一個名字或者一個路徑;用來在getModuleFactory區別模塊,如果這個屬性是undefined // 那么這個模塊將不會被注冊. id : string }
那么,接下來讓我們先來嘗試一個簡單的例子;現在官網的 quickstart
就是一個使用NgModule
的例子,所以我們先按照官網的quickstart來走一遍;如果你翻牆很困難的話可以看看這里 中文版的quickstart ,或者看看我按照官網做的一個例子 angular2-travel .
我們首先來看一下這個最簡單的版本的代碼吧,首先是 app.component.ts
:
import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: 'app/templates/app.template.html' }) export class AppComponent { }
這個就比較簡單了,使用 @Component
裝飾器來定義我們的 AppComponent
組件.重點是 app.module.ts
中的代碼:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
首先導入 NgModule
和 BrowserModule
以及 AppComponent
;NgModule是我們組織Angular應用所必須的,導入 BrowserModule
是因為它提供了啟動和運行瀏覽器應用的那些基本的服務提供商.如果你想深入了解可以看看這里 我應該導入 BrowserModule 還是 CommonModule ,之后的AppComponent是我們要展現的一個最基本的組件.然后我們在 @NgModule
的元數據中配置我們導入的模塊,因為我們需要依賴 BrowserModule
所以我們在 imports
中添加了它,然后我們又在 declarations
和 bootstrap
選項中添加了 AppComponent
組件.
當然我們還需要使用 main.ts
中的代碼來啟動我們整個程序:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app.module'; const platform = platformBrowserDynamic(); platform.bootstrapModule(AppModule);
我們這里使用的是 通過即時JIT編譯器動態引導 的方式來運行我們的代碼;當然還有另一種方式,那就是 使用預編譯器( AoT - Ahead-Of-Time )進行靜態引導. 靜態方案可以生成更小,啟動更快的應用,建議優先使用它,特別是在移動設備或高延遲網絡下.這里我們就不詳細介紹這兩種方式了,在以后的文章中我們會詳細的介紹這兩種方式的區別.
在這里我們先使用第一種方式,我們本篇文章的主要目的是教會大家如何使用 NgModule
.
在 main.ts
中啟動的模塊一般是我們的根模塊,現在我們要來豐富一下我們這個根模塊了.首先我們先來添加一個小組件吧,一般情況下我們的WEB應用都會有一個隨着頁面內容進行變化的標題,那么我們就來先寫這樣一個組件吧:文件路徑: app/components/title/title.component.ts
,代碼如下:
import {Component} from '@angular/core'; @Component({ selector: 'app-title', templateUrl: 'app/components/title/title.template.html' }) export class TitleComponent {}
我們定義了一個組件,然后它的選擇器是 app-title
,組件的模板是:
<p>應用的標題: Dreamapple</p>
然后我們把這個組件添加到我們的根模板里面吧:
<h1>My First Angular App</h1> <app-title></app-title>
然后你會發現,我們的應用報錯了:
zone.js:355 Unhandled Promise rejection: Template parse errors:
'app-title' is not a known element: 1. If 'app-title' is an Angular component, then verify that it is part of this module. 2. If 'app-title' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("<h1>My First Angular App</h1>
這是因為我們沒有把這個組件加入到我們的根模板里面的 declarations
選項里面,然后我們把它加入進去:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import {TitleComponent} from "./components/title/title.component"; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent, TitleComponent // 聲明我們剛剛寫的組件 ], bootstrap: [ AppComponent ] }) export class AppModule { }
如果你覺得我們這個組件有點'死板'的話,我們可以讓它變的靈活一點;我們可以動態的給這個組件傳值,首先修改 title.component.ts
,導入 Input
,然后將組件的輸入顯示到組件中去:
import {Component, Input} from '@angular/core'; @Component({ selector: 'app-title', templateUrl: 'app/components/title/title.template.html' }) export class TitleComponent { @Input() appTitle = ''; }
然后修改模板:
<p>應用的標題: {{appTitle}}</p>
然后修改一下 app.component.ts
里面的內容:
import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: 'app/templates/app.template.html' }) export class AppComponent { appTitle = 'Hello title'; }
最后修改 app.template.html
里面的內容:
<h1>My First Angular App</h1> <app-title [appTitle]="appTitle"></app-title>
然后我們的標題現在就是動態的了,看着還不錯吧.
但是我們這個標題現在還不會變化,我們要想個辦法讓它能夠發生變化;最好的辦法就是使用服務,我們來添加一個讓標題變起來的服務吧,我們給它起名叫 ActiveTitleService
吧.文件的路徑是app/components/title/active-title.service.ts
,代碼如下:
import {Injectable} from '@angular/core'; @Injectable() export class ActiveTitleService { getTitle() { let title = Math.random().toFixed(2) + 'title'; return title; } }
然后我們需要在 app.module.ts
文件中,在 @NgModule
的元數據中添加 providers
然后添加這個服務:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import {TitleComponent} from "./components/title/title.component"; import {ActiveTitleService} from "./components/title/active-title.service"; @NgModule({ providers: [ ActiveTitleService // 添加我們剛才的服務 ], imports: [ BrowserModule ], declarations: [ AppComponent, TitleComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
最后就是在我們的 app.component.ts
中使用了:
import { Component } from '@angular/core'; import {ActiveTitleService} from "./components/title/active-title.service"; @Component({ selector: 'my-app', templateUrl: 'app/templates/app.template.html' }) export class AppComponent { appTitle = 'Hello title'; constructor(activeTitleService: ActiveTitleService) { // 使用這個服務 this.appTitle = activeTitleService.getTitle(); } }
添加完這個服務之后,每次我們刷新頁面,就會發現我們的 appTitle
就會隨之發生變化.這樣下來我們的這個應用就變得很好玩了.然后我想通過指令給我的這個組件添加一些樣式,讓它變得好看一點.
我們再寫這樣一個指令,就叫它 hightlight
吧,文件的路徑是: app/components/title/highlight.directive.ts
,接下來我們會接觸到一些新的內容;但是別緊張,這些內容在后面的章節中我們會詳細的講解的,現在我們需要做的就是先學習如何使用,然后達到我們想要的效果就好了.
import {Directive, ElementRef, Renderer} from '@angular/core'; @Directive({ selector: '[highlight]' }) export class HighlightDirective { constructor(renderer: Renderer, el: ElementRef) { renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'red'); } }
我們可以大概的了解一下上面指令的作用,首先我們導入 Directive
這個裝飾器,用來表示我們下面的那個類是一個指令的類,然后我們導入了 ElementRef
和 Renderer
用來進行操作我們的元素.好,接下來我們就要使用這個指令了,首先我們還是要在 app.module.ts
中聲明這個指令,然后才可以在我們的 title.template.html
中使用:
...
declarations: [
AppComponent,
TitleComponent,
HighlightDirective
],
...
然后我們在模板中使用:
<p highlight>應用的標題: {{appTitle}}</p>
上面的內容都是關於在一個模塊中如何使用 服務
, 指令
, 組件
的;下面我們要寫我們的第二個模塊,主要研究一下在別的模塊中如何使用 服務
, 指令
, 組件
以及模塊之間如何共用組件指令等.
我們的第二個模塊就是一個簡單的列表,展示一些模擬的用戶信息;首先我們創建我們的 UserModule
,因為文件比較多,我就不再一一列舉了,如果你有興趣的話可以在github上面看一下關於這篇文章的具體代碼 angular2-travel .
下面是 UserModule
的一些結構,我下面簡單的講解一下一些主要的部分:
.
├── app
├── modules
├── user.module.ts # 用戶模塊 ├── components ├── user-list # 用戶列表模塊 ├── user.class.ts # 用戶類用來創建用戶實例 ├── user-highlight.directive.ts # 指令 ├── user-list.component.ts # 用列表組件 ├── user-list.services.ts # 獲取用戶列表的服務 ├── user-list.template.html # 用戶列表的模板 ├── ..
首先是 user.module.ts
這個文件:
import {NgModule} from '@angular/core'; import {CommonModule} from "@angular/common"; import {FormsModule} from "@angular/forms"; import {UserListComponent} from "../components/user-list/user-list.component"; import {UserListService} from "../components/user-list/user-list.service"; import {HighlightDirective} from "../components/user-list/user-highlight.directive"; @NgModule({ providers: [ UserListService ], imports: [ CommonModule, FormsModule ], declarations: [ UserListComponent, HighlightDirective ], exports: [ CommonModule, FormsModule, UserListComponent ] }) export class UserModule {}
我們重新定義了一個功能模塊,導入了我們需要的服務 UserListService
,我們需要的模塊 CommonModule
和 FormsModules
;然后聲明了在這個模塊可以使用的組件 UserListComponent
和指令 HighlightDirective
,最后我們導出了一些模塊和組件,
供其它的模塊調用.然后我們就可以直接在我們的根模塊中使用 UserListComponent
了,別忘了修改 app.module.ts
和 app.template.html
;它們的修改如下;
首先是 app.module.ts
:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import {TitleComponent} from "./components/title/title.component"; import {ActiveTitleService} from "./components/title/active-title.service"; import {HighlightDirective} from "./components/title/highlight.directive"; import {UserModule} from "./modules/user.module"; @NgModule({ providers: [ ActiveTitleService ], imports: [ BrowserModule, UserModule // 添加我們需要的UserModule模塊 ], declarations: [ AppComponent, TitleComponent, HighlightDirective ], bootstrap: [ AppComponent ] }) export class AppModule { }
然后是 app.template,html
:
<h1>My First Angular App</h1> <app-title [appTitle]="appTitle"></app-title> <!-- 可以直接使用UserListComponent --> <user-list></user-list>
到這里,我想你已經大概了解了如何使用 NgModule
,如果你想詳細了解一下關於這部分的內容,你可以看看這里 ANGULAR模塊(NGMODULE) ;我們這篇文章只是簡單地介紹了一下,作為入門吧.
最后,有什么問題你都可以在 這里 提出來,或者在下面留言;當然歡迎star這個項目 angular2-travel ,我們更希望您能加入進來,為這個項目出一份力,讓更多的人可以更好地學習使用 Angular2