Subscribed unsubscribe Subscribe Subscribe

AngularJS2 Tour of Heroesしてみる

Tutorial: Tour of Heroes - ts

github.com

今回AngularJS2のLearning Pathの3までやってみました。
https://angular.io/docs/ts/latest/guide/

そこ中での要点を記載していきます。

Interface or Class?

If we need a Hero that goes beyond simple properties, 
a Hero with logic and behavior, we must define a class. 

If we only need type checking, the interface is sufficient and lighter weight.

Transpiling a class to JavaScript produces code. 
Transpiling an interface produces — nothing. 

If the class does nothing (and there is nothing for a Hero class to do right now)
, we prefer an interface.

※特に何もしないなら、コードを生み出さないインターフェイスにしたほうがよいとのことです。

Two-Way Binding

  • [(ngModel)]="XXXXXXXX"を使用する
<h2>{{hero.name}} details!</h2>
.....
<input [(ngModel)]="hero.name" placeholder="name">

※これでhero.nameを使用している箇所が同時に変更されるようになります

*ngFor

<li *ngFor="#hero of heroes">
  <span class="badge">{{hero.id}}</span> {{hero.name}}
</li>

※*はマスターテンプレートを構成することを示します
※#heroはローカル変数であることを示します(使用する場合はhero)

The (*) prefix to ngFor indicates that the <li> element 
and its children constitute a master template.

The ngFor directive iterates over the heroes array returned by the AppComponent.heroes property 
and stamps out instances of this template.

The # prefix before "hero" identifies the hero as a local template variable. 

Focus on the event binding

(click)="onSelect(hero)"

※()はイベントを意味します。

The parenthesis identify the <li> element’s click event as the target. 
The expression to the right of the equal sign calls the AppComponent method, 
onSelect(), passing the local template variable hero as an argument.

Expose the selected hero

public selectedHero: Hero;

※選択済みのHeroを格納するプロパティを定義します

*ngIf

<div *ngIf="selectedHero">
.....
</div>

※selectedHeroが存在しない場合はDOMからdivタグを除外してくれます
※トルツメしたいときなどに使います

Styling the selection

[class.selected]="hero === selectedHero"

※heroとselectedHeroが一致した場合はselectedクラスを置いてくれます

Naming conventions

HeroDetailComponent is in a file named hero-detail.component.ts.

All of our component names end in "Component". All of our component file names end in ".component".

※XXX-XXX-XXX-XXX.component.ts→XxxXxxXxxXxxComponentになる

AppComponent binds its selectedHero property to the hero property of our HeroDetailComponent

<my-hero-detail [hero]="selectedHero"></my-hero-detail>

inputs: ['hero']

Notice that the hero property is the target of a property binding — it's in square brackets to the left of the (=).

Angular insists that we declare a target property to be an input property.
If we don't, Angular rejects the binding and throws an error.
※子コンポーネントには[XXX]で渡して、子コンポーネント側ではそれをinputsとして宣言します
※部分テンプレートに変数を渡す感覚です。親から渡されるものを宣言しておくことで可読性が上がります。

The directives array

A browser ignores HTML tags and attributes that it doesn't recognize. 
So does Angular.

We've imported HeroDetailComponent, 
we've used it in the template, 
but we haven't told Angular about it.
↓
We tell Angular about it by listing it in the metadata directives array. 

※依存コンポーネントを宣言するものです

Services

we'll create a single reusable data service and learn to inject it in the components that need it.

import {Injectable} from 'angular2/core';

@Injectable()
export class HeroService {
}

※TypeScript sees the @Injectable() decorator and emits metadata about our service, metadata that Angular may need to inject other dependencies into this service.

Inject the HeroService

・import {HeroService} from './hero.service';
・constructor(private _heroService: HeroService) { }
・providers: [HeroService]

※We have to teach the injector how to make a HeroService by registering a HeroService provider.
※The AppComponent can use that service to get heroes and so can every child component of its component tree.
※子コンポーネントでも使えるようになります

The ngOnInit Lifecycle Hook

The constructor is for simple initializations like wiring constructor parameters to properties.
It's not for heavy lifting.

Angular will call it if we implement the Angular ngOnInit Lifecycle Hook.
Angular offers a number of interfaces for tapping into critical moments in the component lifecycle
: at creation, after each change, and at its eventual destruction.

Each interface has a single method. When the component implements that method, Angular calls it at the appropriate time.

We write an ngOnInit method with our initialization logic inside and leave it to Angular to call it at the right time.

import {OnInit} from 'angular2/core';

export class AppComponent implements OnInit {
  constructor(private _heroService: HeroService) { }
  getHeroes() {
    this.heroes = this._heroService.getHeroes();
  }
  ngOnInit() {
    this.getHeroes();
  }
}

※constructorはプロパティの設定用(ヘビーな処理はさせない)
※初期化時に何らかの処理をしたい場合は最適なタイミングでngOnInit()を読んでくれるため、OnInitを使います

Async Services and Promises

UIをブロックしないために非同期でデータを取得します

getHeroes() {
  this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}

getHeroes() {
  return Promise.resolve(HEROES);
}

Appendix: Shadowing the parent's service

※子コンポーネントでprovidersの宣言は無駄なインスタンスを作成するだけになります

やってみた感じとしては、AngularJS1に比べて、学習コストが低い印象で、誰でも導入しやすい印象です。
loadイベント完了まで、0.71秒とパフォーマンスもよいようです。