Angular2 NgModule 模塊詳解


 

 

我們今天要學習的是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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM