在之前《Angular2初探》一文中我們已經(jīng)將Angular2基于webpack+Typescript的開發(fā)環(huán)境搭建好了斜做,利用這些,我們接著探究一下如何使用組件(Component),路由(Router)與模塊(Module)快速構(gòu)建一個動態(tài)Angular2應(yīng)用。
一、組件(Component)
組件是應(yīng)用視圖的基本單位盖呼,可以相互嵌套(需要在共同的模塊中聲明)。Angular2推薦的應(yīng)用組織方式是將應(yīng)用相關(guān)的樣式碉考,模板以及ts文件寫入同一目錄下塌计。形如:
app
- app.component.css
- app.component.html
- app.component.ts
bye
- bye.component.css
- bye.component.html
- bye.component.ts
hello
- hello.component.css
- hello.component.html
- hello.component.ts
使用Typescript裝飾器語法,我們能夠快速聲明組件侯谁。
components/app/app.component.css
* {
padding: 0;
margin: 0;
}
components/app/app.component.html
<h1>{{title}}</h1>
<a routerLink="/hello">Hello</a>
<a routerLink="/bye">Bye</a>
<!-- 路由插座 -->
<router-outlet></router-outlet>
components/app/app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'main-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'Angular Router App';
}
components/bye/bye.component.css
h2 {
color: blue;
}
components/bye/bye.component.html
<h2>{{title}}</h2>
components/bye/bye.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'bye-app',
templateUrl: './bye.component.html',
styleUrls: ['./bye.component.css']
})
export class ByeComponent {
title = 'Bye Angular 2~';
}
components/hello/hello.component.css
h2 {
color: red;
}
components/hello/hello.component.html
<h2>{{title}}</h2>
components/hello/hello.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'hello-app',
styleUrls: ['./hello.component.css'],
templateUrl: './hello.component.html'
})
export class HelloComponent {
title = 'Hello Angular 2';
}
二锌仅、路由(Router)
Angular2路由有兩種模式章钾,基于“hash URL”模式以及基于HTML5的“pushState”模式:
基于Hash URL —— “l(fā)ocalhost:3000/#/users”
瀏覽器在當(dāng)前地址的 URL 變化時總會往服務(wù)器發(fā)送頁面請求,唯一的例外規(guī)則是:當(dāng)這些變化位于“#”(被稱為“ hash ”)后面時不會發(fā)送热芹。通過把應(yīng)用內(nèi)的路由 URL 拼接在 # 之后贱傀,路由器可以獲得這條“例外規(guī)則”帶來的優(yōu)點
pushState URL —— “l(fā)ocalhost:3000/users”
現(xiàn)代 HTML 5 瀏覽器支持 history.pushState API ,這是一項可以改變?yōu)g覽器的當(dāng)前地址和歷史伊脓,卻又不會觸發(fā)服務(wù)端頁面請求的技術(shù)府寒。路由器可以合成出一個“自然的” URL ,它看起來和那些需要進(jìn)行頁面加載的 URL 沒什么區(qū)別报腔。
Angular2框架默認(rèn)的路由方式采用的是第二種株搔,基于HTML5的“pushState”的路由。本文推薦大家也去使用這種纯蛾,畢竟在當(dāng)我們真正想要使用錨點(“O朔浚”)進(jìn)行頁面上的一些定位時,不會因使用了HashURL而造成一些困擾翻诉。
不過炮姨,如果真的想要用HTML5路由時,一定需要在頁面<head>...</head>內(nèi)最頂部加上<base href="" />這一標(biāo)簽碰煌。如果沒有此標(biāo)簽舒岸,當(dāng)通過“深鏈接”進(jìn)入該應(yīng)用時,瀏覽器就不能加載資源(圖片芦圾、 CSS 蛾派、腳本)。如果有人把應(yīng)用的鏈接粘貼進(jìn)瀏覽器的地址欄或從郵件中點擊應(yīng)用的鏈接時堕扶,這種問題就會發(fā)生碍脏。
所以梭依,在我們的入口html文件中稍算,我們需要添加之。
index.html
<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>Angular With Webpack</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<main-app>Loading...</main-app>
</body>
</html>
Angular2路由功能通過RouterModule提供役拴,我們需要在路由數(shù)組中定義路由規(guī)則糊探,然后將這些規(guī)則暴露給模塊。
apps/hello.routing.ts
import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HelloComponent } from '../components/hello/hello.component';
import { ByeComponent } from '../components/bye/bye.component';
const helloRoutes: Routes = [{
path: 'hello',
component: HelloComponent
}, {
path: 'bye',
component: ByeComponent
}, {
path: '', // 空路徑規(guī)則河闰,表征任何不符合規(guī)則的路由皆按此規(guī)則進(jìn)行跳轉(zhuǎn)
redirectTo: '/hello', // 重定向至“/hello”
pathMatch: 'full' // 路徑匹配規(guī)則
}];
export const routing: ModuleWithProviders = RouterModule.forRoot(helloRoutes);
三科平、模塊(Module)
模塊是組織應(yīng)用程序和使用外部程序庫的最佳途徑。
很多 Angular 庫都是模塊姜性,比如:FormsModule、HttpModule部念、RouterModule弃酌。很多第三方庫也封裝成了 Angular 模塊,比如:MaterialDesign 查蓉、Ionic 豌研、AngularFire2 鹃共。
Angular 模塊把組件及汉、指令和管道打包成內(nèi)聚的功能塊屯烦,每塊聚焦于一個特性分區(qū)坷随、業(yè)務(wù)領(lǐng)域、工作流驻龟,或一組通用的工具温眉。
模塊還能用來把服務(wù)加到應(yīng)用程序中。這些服務(wù)可能是內(nèi)部研發(fā)的翁狐,比如應(yīng)用日志服務(wù)类溢;也可能是外部資源,比如 Angular 路由和 Http 客戶端露懒。模塊可能在應(yīng)用啟動時主動加載闯冷,也可能由路由器進(jìn)行異步 * 惰性加載 * 。
Angular 模塊是一個由@NgModule裝飾器提供元數(shù)據(jù)的類懈词,元數(shù)據(jù)包括:
- 聲明哪些組件蛇耀、指令、管道屬于該模塊坎弯。
- 公開某些類纺涤,以便其它的組件模板可以使用它們。
- 導(dǎo)入其它模塊抠忘,從其它模塊總獲得本模塊所需的組件撩炊、指令和管道。
- 在應(yīng)用程序級提供服務(wù)崎脉,以便應(yīng)用中的任何組件都能使用它拧咳。
每個 Angular 應(yīng)用至少有一個模塊類—— * 根模塊 * ,我們將通過引導(dǎo)根模塊來啟動應(yīng)用囚灼。
對于組件很少的簡單應(yīng)用來說骆膝,只用一個 * 根模塊 * 就足夠了砾淌。隨著應(yīng)用規(guī)模的增長,我們可以從 * 根模塊 * 中重構(gòu)出一些 ** 特性模塊 ** 谭网,用它們來實現(xiàn)一組密切相關(guān)的功能汪厨。
簡而言之,模塊就是一個集裝箱愉择,里面有各種組件劫乱,以及一定的路由規(guī)則,我們只需要使用特定的方法锥涕,啟動這個模塊即可衷戈。
我們的組件與路由都已準(zhǔn)備好,接下來就是“組裝”的過程了层坠。
apps/hello.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from '../components/app/app.component';
import { HelloComponent } from '../components/hello/hello.component';
import { ByeComponent } from '../components/bye/bye.component';
import { routing } from './hello.routing';
@NgModule({
imports: [
BrowserModule,
routing
],
declarations: [
AppComponent,
HelloComponent,
ByeComponent
],
bootstrap: [ AppComponent ]
})
export class HelloModule {}
組裝完畢殖妇,在入口ts中啟用這個模塊。
main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { HelloModule } from './apps/hello.module';
if (process.env.ENV === 'production') {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(HelloModule);
另有兩個ts文件也得加上
polyfills.ts(js補(bǔ)镀苹ā)
import 'core-js/es6';
import 'core-js/es7/reflect';
require('zone.js/dist/zone');
if (process.env.ENV === 'production') {
// Production
} else {
// Development
Error['stackTraceLimit'] = Infinity;
require('zone.js/dist/long-stack-trace-zone');
}
vendor.ts(方便webpack抽取公共js類庫)
// Angular
import '@angular/platform-browser';
import '@angular/platform-browser-dynamic';
import '@angular/core';
import '@angular/common';
import '@angular/http';
import '@angular/router';
// RxJS
import 'rxjs';
// Other vendors for example jQuery, Lodash or Bootstrap
// You can import js, ts, css, sass, ...
四谦趣、編譯運(yùn)行
npm start
或者
webpack-dev-server --inline --progress --port 8080
嗯,不太美觀座每,不過這個目前并不重要前鹅,至少我們把架子搭了起來,剩下就是往里面填充實際的內(nèi)容峭梳。
看到這里舰绘,相信各位對Angular2應(yīng)用的組織有了一個相對直觀的了解,“組件-路由-模塊”關(guān)系形如下圖:
我們在路由中定義視圖跳轉(zhuǎn)規(guī)則葱椭,在模塊中注入這些路由與視圖組件捂寿。通過“組件-路由-模塊”的組合,在Angular2平臺之上孵运,我們便能夠構(gòu)建出豐富多彩的動態(tài)應(yīng)用來秦陋。
源碼與腳手架工程托管在github之上,有需要的讀者可以自行clone之~
git clone https://github.com/HalZhan/myAngular2.git