Angular 一定會有一個 root module,但你也可以有 feature module,接著就來看看怎麼建立吧!
接續上一篇,假設我們依舊有CreditCardMaskPipe
、 CreditCardService
、CreditCardComponent
,但我們不想要直接放進 root module,我們想要再建立一個 module 來包裝這些東西,這時候新的 module 就是 feature module 了。
首先我們先創一個新的資料夾給新的 module
├── app
│ ├── app.component.ts
│ └── app.module.ts
├── credit-card
│ ├── credit-card-mask.pipe.ts
│ ├── credit-card.component.ts
│ ├── credit-card.module.ts
│ └── credit-card.service.ts
├── index.html
└── main.ts
現在有兩個資料夾裝有 module 了:app.module.ts
和 credit-card.module.ts
先看看後者
//credit-card/credit-card.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CreditCardMaskPipe } from './credit-card-mask.pipe';
import { CreditCardService } from './credit-card.service';
import { CreditCardComponent } from './credit-card.component';
@NgModule({
imports: [CommonModule],
declarations: [
CreditCardMaskPipe,
CreditCardComponent
],
providers: [CreditCardService],
exports: [CreditCardComponent]
})
export class CreditCardModule {}
我們已經知道這個是一個 feature module,但看一下內容其實跟 root module 長得很像,但仍然有幾點不同:
CommonModule
而非 BrowserModule
@NgModule
裡面多了 export
,declarations
宣告用到的物件是 private,為了讓我們的 module 在被其他 module 使用的時候也可以動用自己模組裡的物件,export
可以讓 CeditCardComponent
變成 public, up 因為 AppComponent
之後會用到。但是 CreditCardMaskPipe
則繼續保持 private,因為這只有在自己模組中的溝通才會用到。接著來看看 AppModule
如何使用 CreditCardModule
app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CreditCardModule } from '../credit-card/credit-card.module';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule,
CreditCardModule
],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
imports
中引入要使用的其他模組
剛剛已經說 CeditCardComponent
被模組公開了,所以 AppComponent
這邊就可以拿來使用囉
//app/app.component.ts
...
@Component({
...
template: `
...
<app-credit-card></app-credit-card>
`
})
export class AppComponent {}
因為我們不再直接定義每個 component 他們所需要的 component 和 directive。所以我們需要知道 Angular Module 如何處理指令和組件同時作用在同一個元件上時候的衝突。也就是都針對同一個 selector
時候會怎麼做。
現在假設有兩個指令,針對同一個元件作用。
使背景變藍,字變灰
//blue-highlight.directive.ts
import { Directive, ElementRef, Renderer } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class BlueHighlightDirective {
constructor(renderer: Renderer, el: ElementRef) {
renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'blue');
renderer.setElementStyle(el.nativeElement, 'color', 'gray');
}
}
背景變黃
//yellow-highlight.directive.ts
import { Directive, ElementRef, Renderer } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class YellowHighlightDirective {
constructor(renderer: Renderer, el: ElementRef) {
renderer.setElementStyle(el.nativeElement, 'backgroundColor', 'yellow');
}
}
一個要讓背景變黃,一個要讓背景變藍,這時候會怎樣?
AppModule
這樣定義
//app.module.ts
// Imports
@NgModule({
imports: [BrowserModule],
declarations: [
AppComponent,
BlueHighlightDirective,
YellowHighlightDirective
],
bootstrap: [AppComponent]
})
export class AppModule { }
我們的組件長這樣,其中的 appHighlight
就是被兩個指令同時作用的東西。
//app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<h1 appHighlight>My Angular 2 App</h1>'
})
export class AppComponent {}
所以最後結論是如何?
答案是字是灰色,背景是黃色 (Plurk)
還記得剛剛的 module 嗎?
declarations: [
...,
BlueHighlightDirective,
YellowHighlightDirective
]
BlueHighlightDirective
先被執行, YellowHighlightDirective
再被執行,所以背景先變藍色後來又變成黃色。
結論就是當衝突發生時,當許多指令作用在同一個元件時,會依照順序執行。