2016年5月22日 星期日

Angular2.0 快速開發初體驗

 雖然Angular 1.0 邁向2.0已經有一段的時間了,他們終於釋出正式版囉… 結果不出所料和先前測試版的設定有一點不一樣,好在不是大改…  不然就是悲劇收場。

一、NPM 安裝套件要更到最新版
更新npm 的語法
npm install npm -g
 
筆者一直更新npm套件後,檢查版本均為1.4.28,所以無法成功下戴相關

angular2的套件,最後大絕招直接把原本下戴的套件直接殺了,預設路徑C:\Program Files (x86)\nodejs\node_modules ,然後到暫存檔C:\Users\RDCP01\AppData\Local\Temp 把下戴的npm更新包,重新解壓縮到預設路徑即可…  終於可以更新了… 

 

二、架設Angular的環境
官網上說明很清楚如何先加入哪些設定檔,以下資料夾內容如下展示


Package.json : 下戴相依性的套件
{
  "name": "angular2-quickstart",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "lite": "lite-server",
    "postinstall": "typings install",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "typings": "typings"
  },
  "license": "ISC",
  "dependencies": {
    "@angular/common""2.0.0-rc.1",
    "@angular/compiler""2.0.0-rc.1",
    "@angular/core""2.0.0-rc.1",
    "@angular/http""2.0.0-rc.1",
    "@angular/platform-browser""2.0.0-rc.1",
    "@angular/platform-browser-dynamic""2.0.0-rc.1",
    "@angular/router""2.0.0-rc.1",
    "@angular/router-deprecated""2.0.0-rc.1",
    "@angular/upgrade""2.0.0-rc.1",
    "systemjs": "0.19.27",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "^0.1.3",
    "rxjs": "5.0.0-beta.6",
    "zone.js": "^0.6.12",
    "angular2-in-memory-web-api": "0.0.7",
    "bootstrap": "^3.3.6"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0",
    "typescript": "^1.8.10",
    "typings":"^0.8.1"
  }
}

tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

tsconfig.json
{
  "ambientDependencies": {
    "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654",
    "jasmine": "registry:dt/jasmine#2.2.0+20160412134438",
    "node": "registry:dt/node#4.0.0+20160509154515"
  }
}

systemjs.config.js
 (function (global) {
    // map tells the System loader where to look for things
    var map = {
        'app': 'app', // 'dist',
        'rxjs': 'node_modules/rxjs',
        'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
        '@angular': 'node_modules/@angular'
    };
    // packages tells the System loader how to load when no filename and/or no extension
    var packages = {
        'app': { main: 'main.js', defaultExtension: 'js' },
        'rxjs': { defaultExtension: 'js' },
        'angular2-in-memory-web-api': { defaultExtension: 'js' },
    };
    var packageNames = [
      '@angular/common',
      '@angular/compiler',
      '@angular/core',
      '@angular/http',
      '@angular/platform-browser',
      '@angular/platform-browser-dynamic',
      '@angular/router',
      '@angular/router-deprecated',
      '@angular/testing',
      '@angular/upgrade',
    ];
    // add package entries for angular packages in the form '@angular/common': { main: 'index.js', defaultExtension: 'js' }
    packageNames.forEach(function (pkgName) {
        packages[pkgName] = { main: 'index.js', defaultExtension: 'js' };
    });
    var config = {
        map: map,
        packages: packages
    }
    System.config(config);
})(this);


三、執行指令

下戴angular2 的指令,自動會下戴packet.json的相依套件
npm install

啟動angular2
npm start

一切就這麼簡單…  從零開始…

四、Angular2的其他設定

如果大家有個Happy Start就繼續往下GO,如何才能完成Aangular2 的簡易版quick-start,先建立app資料夾,並加入以下檔案

app.component.ts
import { Component } from '@angular/core';
import { HeroDetailComponent } from './hero-detail.component';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App {{hero}}</h1><my-hero-detail></my-hero-detail>',
    directives: [HeroDetailComponent]
})
export class AppComponent {
    hero = 'Windstorm';
}

在這次的案例中,我就用多組件的案例呈現,angular2傾向於組件為主,所以允許部份組件可以重複使用,延用之前的語法{{}},用來呈現變數內容,其他相關的設定如下說明:

import component: import { HeroDetailComponent } from './hero-detail.component';
引用其他的組件名稱為HeroDetailComponent】,來自hero-detail.component.ts 的畫面範本

directives      : [HeroDetailComponent]
使用組件名稱【HeroDetailComponent】,到時就能在範本中使用此組件的selector name
  
hero-detail.component.ts 
import { Component, Input } from '@angular/core';
@Component({
    selector: 'my-hero-detail',
    template: `<table class="table">
    <tr>
        <th>hero system</th>
     </tr>
    <tr *ngFor = "let hero of heroes" >
    <td>{{hero}}</td>
    </tr>
    </table>`
})
export class HeroDetailComponent {
    heroes=["超人","x man","ice man","gad","spider man"]
}


*ngFor:延用angular1的廻圈語法,只是語法有些微不同
template:  html範本想要折行比較可維護性,請用鍵盤的【~】的上面的` ` 引號括起來喔,一般的引號會出錯。

main.ts
import { bootstrap }    from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';
bootstrap(AppComponent);

原本測試版的檔案是boot.ts,但後來改為main.ts,內容也有些微不同

畫面呈現

補充說明: 如果想將注入的資料抽離獨立函式,如同angular1.0servicefactory 的模式示範:

app.component.ts
import { Component } from '@angular/core';
import { HeroDetailComponent } from './hero-detail';
@Component({
    selector: 'my-app',
    template: '<h1>{{title}}</h1><h2>My Heroes</h2><hero-detail></hero-detail>',
    directives: [HeroDetailComponent]
})
export class AppComponent {
    title = 'Tour of Heroes';  
}
如同上面的範例,引用component 組件

hero.ts : 物件宣告的方式
export class Hero {
    id: number;
    name: string;
}
用來傳遞物件內容,前端也走物件導向… 所以酷吧!

hero-service.ts  服務
import { Injectable } from '@angular/core';
import { Hero } from './hero'
@Injectable()
export class HeroService {
    getHeroes() {
        var HEROES: Hero[] = [
            { 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 Promise.resolve(HEROES);
    }     
}
Angular2.0service程序比較複雜,先要宣告import { Injectable } from '@angular/core';
宣告service的類別之前要呼叫@Injectable() 但還沒瞭解其用意…

眼尖的大家有發現 return Promise.resolve(HEROES); 到底是什麼東東? 查了不少文件原來是javascript的非同步的一種方式,不過這不是本議題範圍… 跳過

hero-detail.ts
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero-service';
@Component({
    selector: '<hero-detail>',
    template: '<ul><li *ngFor ="let hero of heroes" ><span>{{hero.id}}</span> {{hero.name}}</li></ul>',
    providers: [HeroService]   //注入服務
})
export class HeroDetailComponent implements OnInit {
    title = 'Tour of Heroes';
    heroes = [];
    constructor(private heroService: HeroService) { }
    getHeroes() {
        this.heroService.getHeroes().then(heroesaa => this.heroes = heroesaa); // 呼叫service的函式
    }
    ngOnInit() {
        this.getHeroes();  // 呼叫getHeroes函式
    }
}

重頭戲…就在這裡囉… 前面那麼辛苦的建立servicehero物件,就是在這裡要用上了…
import { Component, OnInit } from '@angular/core'; //加入OnInit 初始化時執行的函式
import { Hero } from './hero';                    //匯入Hero的物件類別
import { HeroService } from './hero-service';    //匯入服務的類別名稱

providers: [HeroService]: 注入heroService服務

感謝大家… 有耐心的看完喔~  

沒有留言:

張貼留言