1. 程式人生 > >angular2(v 1.0)

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匯入相應模組,裡面資料內容有具體需求決定。