angular2(v 1.0)
step1:
先安裝node,去官網下載,不多提了。
step2:
建立專案根資料夾並建立如下目錄:
其中,node_modules可以先不建立,是由後續命令生成的;systemjs.config.js和tsconfig.json是angular2的配置檔案;package.json是安裝的依賴包。
各檔案內容為:
/**
* systemjs.config.js
*/
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:' : 'node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js' ,
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js' ,
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
})(this);
/**
* tsconfig.json
*/
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [ "es2015", "dom" ],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
},
"exclude": [
"node_modules/*",
"**/*-aot.ts"
]
}
/**
* package.json
*/
{
"name": "angular2",
"version": "1.0.0",
"description": "QuickStart package.json from the documentation, supplemented with testing support",
"scripts": {
"start": "tsc && concurrently \"tsc -w\" \"lite-server\" ",
"e2e": "tsc && concurrently \"http-server -s\" \"protractor protractor.config.js\" --kill-others --success first",
"lint": "tslint ./app/**/*.ts -t verbose",
"lite": "lite-server",
"pree2e": "webdriver-manager update",
"test": "tsc && concurrently \"tsc -w\" \"karma start karma.conf.js\"",
"test-once": "tsc && karma start karma.conf.js --single-run",
"tsc": "tsc",
"tsc:w": "tsc -w"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@angular/common": "~2.2.0",
"@angular/compiler": "~2.2.0",
"@angular/core": "~2.2.0",
"@angular/forms": "~2.2.0",
"@angular/http": "~2.2.0",
"@angular/platform-browser": "~2.2.0",
"@angular/platform-browser-dynamic": "~2.2.0",
"@angular/router": "~3.2.0",
"angular-in-memory-web-api": "~0.1.15",
"systemjs": "0.19.40",
"core-js": "^2.4.1",
"reflect-metadata": "^0.1.8",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.26"
},
"devDependencies": {
"concurrently": "^3.1.0",
"lite-server": "^2.2.2",
"typescript": "^2.0.10",
"canonical-path": "0.0.2",
"http-server": "^0.9.0",
"tslint": "^3.15.1",
"lodash": "^4.16.4",
"jasmine-core": "~2.4.1",
"karma": "^1.3.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-htmlfile-reporter": "^0.3.4",
"karma-jasmine": "^1.0.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "4.0.9",
"webdriver-manager": "10.2.5",
"rimraf": "^2.5.4",
"@types/node": "^6.0.46",
"@types/jasmine": "^2.5.36",
"@types/selenium-webdriver": "^2.53.33"
},
"repository": {}
}
以下是實現 ‘hello world’ 相應程式碼
/**
* index.html
*/
<!DOCTYPE html>
<html>
<head>
<title>Angular QuickSt2</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading AppComponent content here ...</my-app>
</body>
</html>
/**
* styles.css(沒啥用)
*/
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
/**
* app.component.ts
*/
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>`,
})
export class AppComponent {
name = 'World';
}
/**
* 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 { }
/**
* main.ts
*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
step3:
執行命令,生成node_modules資料夾,安裝依賴
npm install
執行之後就跟開始的目錄結構是一樣的了。
step4:
執行下面命令,程式就跑起來了
npm start
這個命令會在監視模式下執行編譯器,啟動開發伺服器,在瀏覽器中啟動我們的應用,並在我們構建程式碼的時候讓應用得以持續執行
這個時候的目錄結構是這樣的,他會將ts檔案編譯成js檔案:
執行效果如下:
到此,基本的程式已經可以運行了,接下來就可以編寫程式碼完成更豐富的程式。
進階
雙向繫結需要匯入FormsModule模組,新增在imports陣列中(在app.module.ts中imports陣列中是應用中用到的外部模組列表);
雙向資料繫結:
<h2>{{hero.name}} details!</h2>
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name">
</div>
*ngFor、事件繫結和新增selected樣式
<li *ngFor="let hero of heroes"
[class.selected]="hero === selectedHero"
(click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
ngFor的*字首表示< li>及其子元素組成了一個主控模板。
ngFor指令在AppComponent.heroes屬性返回的heroes陣列上迭代,並輸出此模板的例項。
圓括號表示< li>元素上的click事件就是我們要繫結的目標。 等號右邊的表示式呼叫AppComponent的onSelect()方法,並把模板輸入變數hero作為引數傳進去。
定義方法
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
建立元件基本格式
/**
*hero-detail.component.ts
*/
import { Component, Input } from '@angular/core';
@Component({
selector: 'my-hero-detail',
})
export class HeroDetailComponent {
}
自定義元件完成之後先在AppModule中用import匯入,然後在新增到declarations陣列中
declarations陣列
新增HeroDetailComponent到NgModule裝飾器中的declarations陣列。這個陣列包含了所有屬於本應用模組的,由我們親自建立的元件、管道和指令。
命名約定
你會注意到,在名叫app.component.ts的檔案中有一個AppComponent元件,在名叫hero-detail.component.ts的檔案中有一個HeroDetailComponent元件。
我們的所有元件名都以Component結尾。所有元件的檔名都以.component結尾。
這裡我們使用小寫中線命名法(也叫烤串命名法)拼寫檔名, 所以不用擔心它在伺服器或者版本控制系統中出現大小寫問題。
框架之間屬性的繫結
<my-hero-detail [hero]="selectedHero"></my-hero-detail>
注意,在等號(=)左邊方括號中的這個hero是屬性繫結的目標。
Angular希望我們把目標屬性定義成元件的輸入屬性,否則,Angular會拒絕繫結,並且丟擲一個錯誤。
@Input()裝飾器
export class HeroDetailComponent {
@Input()
hero = Hero;
}
我們有幾種方式把hero宣告成輸入屬性。 這裡我們採用首選的方式:使用我們前面匯入的@Input裝飾器,為hero屬性加上註解。
可注入的服務
注意,我們引入了Angular的Injectable函式,並通過@Injectable()裝飾器使用這個函式。
當TypeScript看到@Injectable()裝飾器時,就會記下本服務的元資料。如果Angular需要往這個服務中注入其它依賴,就會使用這些元資料。
不要忘了寫圓括號!如果忘了寫,就會導致一個很難診斷的錯誤。
注入 HeroService
constructor(private heroService: HeroService) { }
建構函式自己什麼也不用做,它在引數中定義了一個私有的heroService屬性,並把它標記為注入HeroService的靶點。
現在,Angular將會知道,當它建立AppComponent例項時,需要先提供一個HeroService的例項。
我們還得註冊一個HeroService提供商,來告訴注入器如何建立HeroService。 要做到這一點,我們應該在@Component元件的元資料底部新增providers陣列屬性如下:
providers: [HeroService]
providers陣列告訴Angular,當它建立新的AppComponent元件時,也要建立一個HeroService的新例項。 AppComponent會使用那個服務來獲取英雄列表,在它元件樹中的每一個子元件也同樣如此。
OnInit介面的基本輪廓:
import { OnInit } from '@angular/core';
export class AppComponent implements OnInit {
ngOnInit(): void {
}
}
Angular路由器
是一個可選的外部Angular NgModule,名叫RouterModule。 路由器包含了多種服務(RouterModule)、多種指令(RouterOutlet, RouterLink, RouterLinkActive)、 和一套配置(Routes)。我們將先配置路由。
配置路由需要在 < head > 中新增< base href=”/”>標籤
相應的template也可以換成templateUrl這樣引數可以傳html頁面
@Component({
moduleId: module.id,
selector: 'my-dashboard',
templateUrl: 'dashboard.component.html',
})
使用路由,將下面程式碼放在app.module.ts的imports陣列中
RouterModule.forRoot([
{
path: 'heroes',
component: HeroesComponent
}
])
路由定義包括幾個部分:
path: 路由器會用它來匹配瀏覽器位址列中的地址,如heroes。
component: 導航到此路由時,路由器需要建立的元件(HeroesComponent)。
重定向
{
path: '',
redirectTo: '/dashboard',
pathMatch: 'full'
},
路由模組
典型路由模組值得注意的有:
將路由抽出到一個變數中。你將來可能會匯出它。而且它讓路由模組模式更加明確。
新增RouterModule.forRoot(routes)到imports。
新增RouterModule到exports,這樣關聯模組的元件可以訪問路由的宣告,比如RouterLink和RouterOutlet。
無Declarations!宣告是關聯模組的任務。
如果你有守衛服務,新增模組providers;本例子無守衛服務。
routerLinkActive指令
Angular路由器提供了routerLinkActive指令,我們可以用它來為匹配了活動路由的HTML導航元素自動新增一個CSS類。 我們唯一要做的就是為它定義樣式。++++++++++++
服務Service
- 首先,建立一個服務,如hero.service.ts;
- 匯入(import)想操作的資料和類, 在service中HeroService中寫要操* * 作資料的程式碼邏輯;
- 然後在想使用這個服務的元件(component)中先匯入這個service模組;
- 然後建立HeroService例項(constructor(private heroService: HeroService){ });
- 接著在@Component中註冊一個HeroService的提供商(providers: [HeroService]);
- 可以使用生命週期鉤子來進行操作。
路由引數相關
ngOnInit(): void {
this.route.params
.switchMap((params: Params) => this.heroService.getHero(+params['id']))
.subscribe(hero => this.hero = hero);
}
- switchMap運算子如何將可觀察的路由引數中的 id 對映到一個新的Observable, 即HeroService.getHero方法的結果。
- 如果使用者在 getHero 請求執行的過程中再次導航這個元件,switchMap 再次呼叫HeroService.getHero之前, 會取消之前的請求。
- 英雄的id是數字,而路由引數的值總是字串。 所以我們需要通過 JavaScript 的 (+) 操作符把路由引數的值轉成數字。
獲取路由引數方法
開啟HeroService,並新增一個getHero方法,用來通過id從getHeros過濾英雄列表:
getHero(id: number): Promise<Hero> {
return this.getHeroes()
.then(heroes => heroes.find(hero => hero.id === id));
}
HTTP模組
使用http由於沒有伺服器要使用記憶體Web API服務,需要引入兩個模組:
// Imports for loading & configuring the in-memory web api
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
同時要在imports陣列中加入:
InMemoryWebApiModule.forRoot(InMemoryDataService)
接著建立in-memory-data.service.ts檔案:
import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
let heroes = [
{id: 11, name: 'Mr. Nice'},
{id: 12, name: 'Narco'},
{id: 13, name: 'Bombasto'},
{id: 14, name: 'Celeritas'},
{id: 15, name: 'Magneta'},
{id: 16, name: 'RubberMan'},
{id: 17, name: 'Dynama'},
{id: 18, name: 'Dr IQ'},
{id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'}
];
return {heroes};
}
}
import匯入相應模組,裡面資料內容有具體需求決定。