プログラマーの調べ物

プログラマーが調べ物をするときに役に立つサイトを作ります。

Angular2でルーティング機能を実装する

Angular2でルーティング機能を実装してみます。 Single Page Applicationでは、URLを変更することで、サーバにリクエストを送ることなく、画面に変化をつけることができます。

HashLocationStrategyというのは、ハッシュサイン(#)をURLに付け加えることで、URLを区切る方法です。 今回のサンプルではこのやり方を使います。

ディレクトリ構成は以下のとおりです。

f:id:sho322:20170410234245j:plain

まずはお作法的なファイルからです。

package.jsonを配置して、npm installしてください。

{
  "name": "router-sample",
  "version": "1.0.0",
  "description": "Routing samples",
  "homepage": "",
  "private": true,
  "scripts": {
    "start": "live-server"
  },
  "dependencies": {
    "@angular/common": "^2.4.0",
    "@angular/compiler": "^2.4.0",
    "@angular/core": "^2.4.0",
    "@angular/forms": "^2.4.0",
    "@angular/http": "^2.4.0",
    "@angular/platform-browser": "^2.4.0",
    "@angular/platform-browser-dynamic": "^2.4.0",
    "@angular/router": "^3.4.0",
    "@angular/material": "^2.0.0-beta.2",
    "core-js": "^2.4.1",
    "rxjs": "^5.1.0",
    "zone.js": "^0.7.6",
    "systemjs": "0.19.37"
  },
  "devDependencies": {
    "live-server": "1.0.0",
    "typescript": "^2.0.0"
  }
}

SystemJSの設定ファイルです。

systemjs.config.ts

System.config({
  transpiler: 'typescript',
  typescriptOptions: {emitDecoratorMetadata: true,
    target: "ES5",
    module: "commonjs"},
  map: {
    '@angular': 'node_modules/@angular',
    'rxjs'    : 'node_modules/rxjs'
  },
  meta: {
    '@angular/*': {'format': 'cjs'}
  },
  packages: {
    'app'                              : {main: 'main', defaultExtension: 'ts'},
    'rxjs'                             : {main: 'Rx'},
    '@angular/core'                    : {main: 'bundles/core.umd.min.js'},
    '@angular/common'                  : {main: 'bundles/common.umd.min.js'},
    '@angular/compiler'                : {main: 'bundles/compiler.umd.min.js'},
    '@angular/http'                    : {main: 'bundles/http.umd.min.js'},
    '@angular/router'                  : {main: 'bundles/router.umd.min.js'},
      '@angular/forms'                  : {main: 'bundles/forms.umd.min.js'},
    '@angular/platform-browser'        : {main: 'bundles/platform-browser.umd.min.js'},
    '@angular/platform-browser-dynamic': {main: 'bundles/platform-browser-dynamic.umd.min.js'},
    '@angular/material'                : {main: 'material.umd.js'}

  }
});

TypeScriptの設定ファイル。 tsconfig.json

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "module": "commonjs",
    "target": "ES5"
  },
  "exclude": [
    "node_modules"
  ]
}

そして、index.html

<!DOCTYPE html>
<html>
<head>
  <title>Routing Example</title>

  <link href="node_modules/@angular/material/core/theming/prebuilt/indigo-pink.css" rel="stylesheet">

  <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/typescript/lib/typescript.js"></script>
  <script src="node_modules/systemjs/dist/system.src.js"></script>
  <script src="systemjs.config.js"></script>

  <script>System.import('app').catch(console.error.bind(console));</script>
</head>
<body>
  <app>Loading...</app>
</body>
</html>

では、main.tsを見ていきましょう。

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './components/app.component';
import { HomeComponent } from "./components/home";
import { TestComponent } from "./components/test";
import { routing } from './components/app.routing';

import { LocationStrategy, HashLocationStrategy, APP_BASE_HREF} from '@angular/common';

@NgModule({
    imports:      [ BrowserModule, routing ],
    declarations: [ AppComponent, HomeComponent, TestComponent],
    providers:[{provide: LocationStrategy, useClass: HashLocationStrategy}],
    bootstrap:    [ AppComponent ]  
})
class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

ここではブラウザに最初に読み込まれるスクリプトが書かれています。

読み込まれるコンポーネントを見ていきましょう。

app.component.ts

import {Component} from '@angular/core';
@Component({
    selector: 'app',
    template: `
        <a [routerLink]="['/']">Home</a>
        <a [routerLink]="['test']">Test Page</a>
        <router-outlet></router-outlet>
    `
})
export class AppComponent {}

app.component.tsはmain.tsでbootstrap: [ AppComponent ] と定義されているように、一番最初に表示されるコンポーネントです。

ここではaタグにリンクが設定されてます。routerLinkで設定した値がURLの「#」以降に設定されます。

index.htmlの「app」というタグの場所にapp.component.tsの内容は表示されます。

f:id:sho322:20170410234306j:plain

また、後述するHomeComponentやTestCompentの内容はrouter-outletタグの場所に表示されます。 このrouter-outletタグの名前は変えてはいけません。

次にルーティングの設定。

app.routing.ts

import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from "./home";
import { TestComponent } from "./test";

const routes: Routes = [
    {path: '', component: HomeComponent},
    {path: 'test', component: TestComponent}
];

export const routing = RouterModule.forRoot(routes);

ここではルーティングテーブルが定義されています。

http://127.0.0.1:8080/#/を開こうとすると、 HomeComponentの内容が表示されます。

http://127.0.0.1:8080/#/testを開こうとすると、 TestComponentの内容が表示されます。

home.ts

import {Component} from '@angular/core';

@Component({
    selector: 'home',
    template: '<h1 class="home">This is HomeComponent</h1>',
    styles: ['.home {background: blue}']
})
export class HomeComponent {}

これが上で一度見た、HomeComponentの内容です。 This is HomeComponentという文字が表示されます。

f:id:sho322:20170410234306j:plain

test.tsの内容です。

import { Component } from '@angular/core';

@Component({
    selector: 'test',
    template: '<h1 class="test"> This is TestComponent</h1>',
    styles: ['.test {background: yellow}']
})
export class TestComponent {}

以下のように表示されます。

f:id:sho322:20170410234321j:plain

Angular 2 Development With Typescript

Angular 2 Development With Typescript