我们今天要学习的是Angular2的模块系统,一般情况下我们使用一个根模块去启动我们的应用,然后使用许多的功能模块去丰富我们的应用,扩展我们应用的功能.这些全部依靠我们的NgModule
装饰器,接下来我们就来好好学习一下这个装饰器.当然在这个过程中你会遇到一些新的指令,概念等等;但是别慌,我们会在以后的文章中一个一个的详细讲解呢.
在开始今天的练习之前,我们首先来熟悉一下NgModule
的API,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
interface NgModule {
providers : Provider[]
declarations : Array <Type<any >|any []>
imports : Array <Type<any >|ModuleWithProviders|any []>
exports : Array <Type<any >|any []>
entryComponents : Array <Type<any >|any []>
bootstrap : Array <Type<any >|any []>
schemas : Array <SchemaMetadata|any []>
id : string
}
那么,接下来让我们先来尝试一个简单的例子;现在官网的quickstart
就是一个使用NgModule
的例子,所以我们先按照官网的quickstart来走一遍;如果你翻墙很困难的话可以看看这里中文版的quickstart ,或者看看我按照官网做的一个例子angular2-travel .
我们首先来看一下这个最简单的版本的代码吧,首先是app.component.ts
:1
2
3
4
5
6
import { Component } from '@angular/core' ;
@Component({
selector: 'my-app' ,
templateUrl: 'app/templates/app.template.html'
})
export class AppComponent { }
这个就比较简单了,使用@Component
装饰器来定义我们的AppComponent
组件.重点是app.module.ts
中的代码:1
2
3
4
5
6
7
8
9
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
中的代码来启动我们整个程序:1
2
3
4
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
,代码如下:1
2
3
4
5
6
7
import {Component} from '@angular/core' ;
@Component({
selector: 'app-title' ,
templateUrl: 'app/components/title/title.template.html'
})
export class TitleComponent {}
我们定义了一个组件,然后它的选择器是app-title
,组件的模板是:1
<p > 应用的标题: Dreamapple</p >
然后我们把这个组件添加到我们的根模板里面吧:1
2
<h1 > My First Angular App</h1 >
<app-title > </app-title >
然后你会发现,我们的应用报错了:1
2
3
4
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
选项里面,然后我们把它加入进去:1
2
3
4
5
6
7
8
9
10
11
12
13
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
,然后将组件的输入显示到组件中去:1
2
3
4
5
6
7
8
9
import {Component, Input} from '@angular/core' ;
@Component({
selector: 'app-title' ,
templateUrl: 'app/components/title/title.template.html'
})
export class TitleComponent {
@Input() appTitle = '' ;
}
然后修改模板:1
<p > 应用的标题: {{appTitle}}</p >
然后修改一下app.component.ts
里面的内容:1
2
3
4
5
6
7
8
import { Component } from '@angular/core' ;
@Component({
selector: 'my-app' ,
templateUrl: 'app/templates/app.template.html'
})
export class AppComponent {
appTitle = 'Hello title' ;
}
最后修改app.template.html
里面的内容:1
2
<h1 > My First Angular App</h1 >
<app-title [appTitle ]="appTitle" > </app-title >
然后我们的标题现在就是动态的了,看着还不错吧.
但是我们这个标题现在还不会变化,我们要想个办法让它能够发生变化;最好的办法就是使用服务,我们来添加一个让标题变起来的服务吧,我们给它起名叫ActiveTitleService
吧.文件的路径是app/components/title/active-title.service.ts
,代码如下:1
2
3
4
5
6
7
8
9
import {Injectable} from '@angular/core' ;
@Injectable()
export class ActiveTitleService {
getTitle() {
let title = Math .random().toFixed(2 ) + 'title' ;
return title;
}
}
然后我们需要在app.module.ts
文件中,在@NgModule
的元数据中添加providers
然后添加这个服务:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
中使用了:1
2
3
4
5
6
7
8
9
10
11
12
13
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
,接下来我们会接触到一些新的内容;但是别紧张,这些内容在后面的章节中我们会详细的讲解的,现在我们需要做的就是先学习如何使用,然后达到我们想要的效果就好了.1
2
3
4
5
6
7
8
9
10
11
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
中使用:1
2
3
4
5
6
7
...
declarations: [
AppComponent,
TitleComponent,
HighlightDirective
],
...
然后我们在模板中使用:1
<p highlight > 应用的标题: {{appTitle}} </p >
上面的内容都是关于在一个模块中如何使用服务
,指令
,组件
的;下面我们要写我们的第二个模块,主要研究一下在别的模块中如何使用服务
,指令
,组件
以及模块之间如何共用组件指令等.
我们的第二个模块就是一个简单的列表,展示一些模拟的用户信息;首先我们创建我们的UserModule
,因为文件比较多,我就不再一一列举了,如果你有兴趣的话可以在github上面看一下关于这篇文章的具体代码angular2-travel .
下面是UserModule
的一些结构,我下面简单的讲解一下一些主要的部分:1
2
3
4
5
6
7
8
9
10
11
12
.
├── 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
这个文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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
],
declarations: [
AppComponent,
TitleComponent,
HighlightDirective
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
然后是app.template,html
:1
2
3
4
<h1 > My First Angular App</h1 >
<app-title [appTitle ]="appTitle" > </app-title >
<user-list > </user-list >
到这里,我想你已经大概了解了如何使用NgModule
,如果你想详细了解一下关于这部分的内容,你可以看看这里ANGULAR模块(NGMODULE) ;我们这篇文章只是简单地介绍了一下,作为入门吧.
最后,有什么问题你都可以在这里 提出来,或者在下面留言;当然欢迎star这个项目angular2-travel ,我们更希望您能加入进来,为这个项目出一份力,让更多的人可以更好地学习使用Angular2