國內 Angular2 資料比較少,這裏看到一篇不錯的入門文章就分享過來了 —— Angular 2 快速上手,這裏面還有不少有關於 Angular2 的文章,感興趣的朋友能夠去看一看css
目前angular2已經來到了beta版,這意味着它已經作好了開發出穩定應用的準備了。和angular1.x相比,它發生了許多顛覆性的變化,angular2的官方網站上,有一個5分鐘快速開始教程(angular.io),有興趣的朋友能夠去開一下,幫助你快速的瞭解angular2。在本文中,我將會經過製做一個簡單的小網站,來爲你們展現angular2的新特性,帶領你們走入angular2的全新世界。html
如今有兩種主要的方法配置angular2的應用程序,一個是經過systemjs,而另外一個則是webpack。爲了簡單起見,在本文中將會使用systemjs。
你可使用ES五、EcmaScript 2015 或者 TypeScript來開發你的angular2應用,angular2的團隊的推薦是使用TypeScript開發。在使用TypeScript以前,須要完成一些配置工做,雖然你會感受到有些繁瑣,可是用起來你仍是會感到駕輕就熟的,你的代碼也將會更加清晰明瞭。
咱們先借用在angular2官網的教程中使用的工程 Tour of Heroes 來開始咱們的征程。
你能夠經過git下載這個工程,當你下載下來以後,第一件事應該是用npm i
命令來初始化項目。node
由於咱們是用TypeScript編寫咱們的程序,因此咱們先得在咱們的工程中配置TypeScript,告訴編譯器如何產生JavaScript文件。關於配置文件中的其餘屬性在這裏我就不贅述了,我只介紹兩個最重要的屬性,一個是"target":"ES5"
和"module":"system"
。target
屬性將設置TypeScript編譯出來的ECMAScript版本爲
ES5,"module":"system"
覺得着咱們想用
system的格式來生成咱們的模塊。webpack
{ "compilerOptions": { "target": "ES5", "module": "system", "sourceMap": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, "moduleResolution": "node", "removeComments": false, "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true }, "exclude": [ "node_modules" ] }
咱們已經定義了該如何編譯TypeScript文件,接下來咱們須要在工程的 package.json 文件中添加一些選項。git
"scripts": { "tsc": "tsc", "tsc:w": "tsc -w", "lite": "lite-server", "start": "concurrent \"npm run tsc:w\" \"npm run lite\" " }
Angular2中對於我來講最神祕的一點就是「我該如何運行個人應用?」,第二神祕的一點就是「好吧,我該如何啓動個人應用程序?」github
啓動咱們的應用的第一件事就是在工程的index.html
文件中引用必要的資源。除了angular的資源的以外,最重要的一環就是system.src.js
,用它來做咱們的模塊加載器。web
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="node_modules/rxjs/bundles/Rx.js"></script> <script src="node_modules/angular2/bundles/angular2.dev.js"></script> <script src="node_modules/angular2/bundles/router.dev.js"></script>
咱們打算經過使用systemjs
來輸入咱們的啓動模塊。npm
<script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/boot') .then(null, console.error.bind(console)); </script>
在boot.ts
文件中,咱們輸入了3格組件:bootstrap
、ROUTER_PROVIDERS
和AppComponent
。而後實例化了咱們的應用並指明瞭咱們的根組件,AppComponent
並注入了ROUTER_PROVIDERS
做爲一個子模塊。json
import {bootstrap} from 'angular2/platform/browser'; import {ROUTER_PROVIDERS} from 'angular2/router'; import {AppComponent} from './app.component'; bootstrap(AppComponent, [ ROUTER_PROVIDERS ]);
回到以前的index.html
文件中,<app>Loading...</app>
這一行就是咱們應用的入口標記。Angular已經實例化了AppComponent
而且將它的模板載入到了app
元素中。bootstrap
<body> <app>Loading...</app> </body>
在講解了如何編譯、配置和啓動一個angular2的應用程序以後。讓咱們看一看angular2中組件的組成部分,以便咱們能更好的理解AppComponent
和app
之間的聯繫。
Angular中的組件是angular中最基本的概念之一。一個組件控制一個視圖(View)――一片爲用戶展現信息和響應用戶反饋的網頁。通常來講,一個組件就是一個用於控制視圖模板的JavaScript類。
引用(有關於組件的更多內容,你能夠去閱讀個人《CIDER:建立一個Angular2組件》,你將會了解到如何建立和使用你的組件)
建立組建的第一件事就是先寫一個類(class),咱們先作聲明,一會再來改進它。
export class AppComponent {}
接下來,咱們應該輸入咱們的依賴模塊。在本例中,咱們僅須要從angular2/core
中輸入Component
。
import {Component} from 'angular2/core';
以後,咱們須要裝飾(decorate)咱們的類。經過添加@Component
的元數據來告訴咱們的應用程序,咱們想要一個怎麼樣的AppComponent
。咱們將使用selector
屬性爲咱們的組件取一個HTML元素的名字,這樣就能夠經過定義好的HTML元素的名字來使用組件了。同時還須要經過templateUrl
和styleUrls
爲組件設置模板和樣式。最後,咱們將ROUTER_DIRECTIVES
這個指令經過directives
屬性注入到組件中去。
@Component({ selector: 'app', templateUrl: 'app/app.component.html', styleUrls: ['app/app.component.css'], directives: [ROUTER_DIRECTIVES] }) export class AppComponent {}
在這個示例中,咱們還想增長爲咱們的組件增長路由功能,所以咱們將會使用RouterConfig
模塊,並用@RouterConfig
來裝飾咱們的組件。爲了可以路由,咱們須要在文件中的最頂部輸入RouterConfig
、ROUTER_DIRECTIVES
、AboutComponent
、ExperimentsComponent
和HomeComponent
。
import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; import {AboutComponent} from './about/about.component'; import {ExperimentsComponent} from './experiments/experiments.component'; import {HomeComponent} from './home/home.component';
咱們須要路由模塊來開啓路由功能以及其餘的組件做爲路由的目標。接下來就須要向@RouterConfig
中傳入一組路由的定義,來告訴應用程序路由的路徑、路由的名字和每一個路由所對應的組件。咱們爲home
路由的屬性useAsDefault
設置爲true
,將其做爲默認路由。
@RouteConfig([ {path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true }, {path: '/about', name: 'About', component: AboutComponent }, {path: '/experiments', name: 'Experiments', component: ExperimentsComponent } ])
而後,咱們將StateService
和ExperimentService
輸入到咱們的組件中並放入component
修飾符的providers
屬性中。如下是整個 AppComponent 的代碼。
import {Component} from 'angular2/core'; import {RouteConfig, ROUTER_DIRECTIVES} from 'angular2/router'; import {AboutComponent} from './about/about.component'; import {ExperimentsComponent} from './experiments/experiments.component'; import {HomeComponent} from './home/home.component'; import {StateService} from './common/state.service'; import {ExperimentsService} from './common/experiments.service'; @Component({ selector: 'app', templateUrl: 'app/app.component.html', styleUrls: ['app/app.component.css'], directives: [ROUTER_DIRECTIVES], providers: [StateService, ExperimentsService], }) @RouteConfig([ {path: '/home', name: 'Home', component: HomeComponent, useAsDefault: true }, {path: '/about', name: 'About', component: AboutComponent }, {path: '/experiments', name: 'Experiments', component: ExperimentsComponent } ]) export class AppComponent {}
在完成 App 組件以後,咱們繼續編寫咱們的 Home 組件。首先仍是先定義一個 HomeComponent
類,同時在類中爲組件的標題和內容定義兩個屬性。
export class HomeComponent { title: string = 'Home Page'; body: string = 'This is the about home body'; }
而後輸入合適的依賴模塊。
import {Component} from 'angular2/core';
以後裝飾咱們的類並設置selector
和templateUrl
屬性。
@Component({ selector: 'home', templateUrl: 'app/home/home.component.html' })
而後咱們將爲咱們的組件引用 StateService 並使用它來存儲狀態兩個路由之間的狀態。Angular2中的依賴注入發生在該類的構造函數中,所以咱們將在構造函數中注入 StateService。Angular的每一個組件都有有生命週期的鉤子(lifecycle hooks),咱們能夠按順序使用它們。在本組件中,咱們想在組件初始化的時候從 StateService 中獲取和設置咱們的信息。這時候咱們須要使用ngOnInit
鉤子。(有關於組件的生命週期的詳細內容能夠參考官網教程(https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html))
import {Component} from 'angular2/core'; import {StateService} from '../common/state.service'; export class HomeComponent { title: string = 'Home Page'; body: string = 'This is the about home body'; message: string; constructor(private _StateService: StateService) { } ngOnInit() { this.message = this._StateService.getMessage(); } updateMessage(m: string): void { this._StateService.setMessage(m); } }
許多組件可能會須要訪問相同的一組數據,而咱們並不想像傻瓜同樣的一遍又一遍的複製粘貼一樣的代碼。這個時候,服務(Service)出現了。咱們須要建立一個單一的且能夠重複使用的數據服務,並學會將該服務注入到咱們須要的組件中去。
將數據的存取從新包裝成一個獨立的服務讓組件的重心傾向於對視圖的支持。它能讓組件的單元測試變得更加容易。
在上面的組件中,咱們常常見到一個叫StateService的東西,它究竟是什麼呢?沒錯,它就是一個服務,接下來,讓咱們一步一步的建立它。首先咱們須要聲明一個叫 StateService 的類並將它暴露給咱們的應用程序。
export class StateService { private _message = 'Hello Message'; getMessage(): string { return this._message; }; setMessage(newMessage: string): void { this._message = newMessage; }; }
該服務中定義了_message
屬性以及它的屬性獲取器(getter)和設置器(setter)。咱們要想使StateService可以注入到其餘組件中去,首先須要在咱們的類中輸入Injectable
,並用@Injectable
修飾咱們的類。
import {Injectable} from 'angular2/core'; @Injectable() export class StateService { private _message = 'Hello Message'; getMessage(): string { return this._message; }; setMessage(newMessage: string): void { this._message = newMessage; }; }
好了,如今服務模塊也寫好了,感受咱們的應用終於快完成了,最後也是最重要的一步,就是要描述應用的樣子了。
我將經過home.component.html
做爲切入點來簡單介紹一下 Angular2 中的升級版模板語法(template syntax)。
單向數據綁定與 Angular1.x 中的形式是同樣的,就是經過字符串插入。
<h1>{{title}}</h1> {{body}}
用戶輸入事件再也不經過在咱們的HTML標籤中使用自定義的Angular指令來捕獲,而是經過在插入語句中封裝原生的DOM事件來捕獲它們。咱們能夠在下面代碼中看到,我經過(click)="updateMessage(message)"
來爲元素註冊 click 事件,當事件觸發時調用 updateMessage 方法。
<button type="submit" class="btn" (click)="updateMessage(message)">Update Message</button>
Angular2中的雙向數據綁定基於單向數據綁定。以前咱們看到單向數據綁定中使用了字符串插入的方法,其實在咱們綁定一個元素的屬性時,可使用方括號語法。咱們將屬性綁定(組件到視圖)和事件綁定(視圖到組件)的方法組合起來就是雙向數據綁定了。是否是很神奇?雙向數據綁定的方法很簡單,就是在 ngModel 用方括號和圓括號包起來變成[(ngModel)]=」message
。
<input type="text" [(ngModel)]="message" placeholder="Message">
如下是整個 home.component.html 的內容。
<h1>{{title}}</h1> {{body}} <hr> <div> <h2 class="text-error">Home: {{message}}</h2> <form class="form-inline"> <input type="text" [(ngModel)]="message" placeholder="Message"> <button type="submit" class="btn" (click)="updateMessage(message)">Update Message</button> </form> </div>
接下來,咱們須要回到 app.component.html 中,來探討一下如何在模板語法中加入路由連接。在咱們定義一個路由的時候,每一個組件都有它對應的模板,那麼問題來了,當路由到一個組件的時候,這個模板應該被放在哪裏呢?這個時候,router-outlet
出現了,它告訴應用程序路由中組件的擺放位置。
<div id="container"> <router-outlet></router-outlet> </div>
在定義了路由組件的擺放位置以後,那麼咱們如何從一個路由到另外一個路由呢?RouterLink 就是完成了路由的指向問題。
<h1 id="logo"> <a [routerLink]="['/Home']"></a> </h1> <div id="menu"> <a [routerLink]="['/Home']" class="btn">Home</a> <a [routerLink]="['/About']" class="btn">About</a> <a [routerLink]="['/Experiments']" class="btn">Experiments</a> </div>
整個 app.component.html 文件以下所示:
<header id="header"> <h1 id="logo"> <a [routerLink]="['/Home']"></a> </h1> <div id="menu"> <a [routerLink]="['/Home']" class="btn">Home</a> <a [routerLink]="['/About']" class="btn">About</a> <a [routerLink]="['/Experiments']" class="btn">Experiments</a> </div> <div class="color"></div> <div class="clear"></div> </header> <div class="shadow"></div> <div id="container"> <router-outlet></router-outlet> </div>
到此爲止,咱們的網頁算是完成了,在你拿出去炫耀以前,讓咱們回顧一下咱們的製做過程:
一、咱們配置了tsconfig.json文件來講明TypeScript該如何編譯。二、咱們學習瞭如何簡單的使用systemjs來處理模塊的載入並引導咱們應用程序的啓動。三、咱們瞭解了該如何建立 AppComponent 和 HomeComponent。四、咱們學習瞭如何使用 @Injectable() 建立一個可注入的服務。五、咱們稍微瞭解了一下Angular2中的綁定語法。六、咱們學習瞭如何用 router-outlet 在視圖中定義路由組件存放的位置,並使用 routerLink 進行路由之間的跳轉。