Angular 2 Beta、ヒーローズツアーチュートリアルパート3

パート1 パート2 パート3 パート4







私たちのアプリケーションは成長しています。 このパートでは、データをコンポーネントに転送するだけでなく、再利用可能なコンポーネントに焦点を当てます。 ヒーローのリストを個別のコンポーネントに分け、このコンポーネントを再利用に適したものにしましょう。







アプリケーションを起動する、パート3







私たちが泊まった場所



ヒーローツアーを続ける前に、プロジェクトが次の構造を持っていることを確認しましょう。 そうでない場合は、前の章に戻る必要があります。







angular2-tour-of-heroes app app.component.ts main.ts node_modules ... typings ... index.html package.json tsconfig.json typings.json
      
      





コード変換とアプリケーション実行をサポート



TypeScriptコンパイラを実行して、ファイルの変更を監視し、すぐにコンパイルし、Webサーバーを起動する必要があります。 入力することでこれを行います







  npm start
      
      





これにより、ヒーローツアーの作成を継続している間、アプリケーションが実行され続けます。







ヒーロー詳細情報コンポーネントの作成



ヒーローのリストとヒーローに関する詳細情報は、同じコンポーネントの1つのファイルにあります。 これまでのところ、それらは小さいですが、それぞれ成長することができます。 そのうちの1つに対して新しい要件を取得できます。これには、1つだけを変更する必要があり、もう1つは変更しません。 ただし、各変更には2つのコンポーネントのエラーのリスクが伴い、テストが2倍になります。 ヒーローに関する詳細情報をアプリケーションの他の場所で再利用する必要がある場合、ヒーローのリストを取得する必要があります。







私たちの現在の構成要素は、 単一の責任原則に違反しています。 この教材は単なるレッスンにすぎませんが、特に難しいことではないので、正しく行うことができます。 さらに、このプロセスでは、Angularでアプリケーションを構築する方法について詳しく学習します。







ヒーローに関する詳細情報を独自のコンポーネントに抽出してみましょう。







主人公に関する詳細情報を個別に



以下に示すように、 hero-detail.component.ts



という新しいファイルをapp



フォルダーに追加し、 hero-detail.component.ts



を作成します。







hero-detail.component.ts(初期バージョン)







  import {Component, Input} from 'angular2/core'; @Component({ selector: 'my-hero-detail', }) export class HeroDetailComponent { }
      
      





命名規則


どのクラスがコンポーネントであるか(クラス名ごと)およびどのファイルがコンポーネントを含むか(ファイル名ごと)を一目で理解したいと思います。







AppComponent



という名前のファイルにapp.component.ts



あり、新しいHeroDetailComponent



hero-detail.component.ts



という名前のファイルにあることに注意してください。







すべての複合クラス名は「Component」で終わります。 複合ファイル名はすべて「.component」で終わります。







ファイル名を「ダッシュ付き小文字」(kebab-case)に変換するため、サーバーまたはバージョン管理システムでの大文字と小文字の区別については心配しません。







上記のコードを検討してください。







Angularデコレータ-ComponentおよびInput



インポートすることから始めました。すぐに必要になるからです。

次に、 @Component



デコレータを使用してメタデータを作成します。ここで、コンポーネント要素を識別するセレクタの名前を指定します。 次に、クラスをエクスポートして、他のコンポーネントで使用できるようにします。







ここで終了したら、 AppComponent



インポートして、対応する要素を作成します。

<my-hero-detail>









ヒーロー詳細テンプレート



現在、 ヒーローヒーローの詳細ビューはAppComponent



1つのテンプレートに結合されていAppComponent



ヒーロー詳細のコンテンツをAppComponent



からクリップして、新しいHeroDetailComponent



テンプレートHeroDetailComponent



貼り付けましょう。







以前は、 AppComponent



selectedHero.name



プロパティをバインドしました。 HeroDetailComponent



には、 HeroDetailComponent



プロパティではなく、 hero



プロパティがあります。 したがって、新しいテンプレート全体でselectedHero



hero



置き換えます。 これが唯一の変更です。 結果は次のようになります。







hero-detail.component.ts(テンプレート)







  template: ` <div *ngIf="hero"> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"/> </div> </div> `
      
      





これで、ヒーローに関する詳細情報のマークアップはHeroDetailComponent



のみ存在します。







ヒーロープロパティの追加



上記で説明したhero



プロパティをコンポーネントクラスに追加します。







  hero: Hero;
      
      





ああ、ああ。 hero



プロパティをHero



タイプとして宣言しましたが、ヒーロークラスはapp.component.ts



ファイルにあります。 2つのコンポーネントがあり、それぞれが独自のファイルでHero



クラスを参照する必要があります。







Hero



クラスをapp.component.ts



から独自のhero.ts



ファイルに移動することにより、この問題を解決します。







hero.ts(エクスポートされたヒーロークラス)







  export class Hero { id: number; name: string; }
      
      





両方のコンポーネントファイルで参照する必要があるため、 hero.ts



からHero



クラスをエクスポートします。 app.component.ts



およびhero-detail.component.ts



上部に次のimportステートメントを追加します。







hero-detail.component.tsおよびapp.component.ts(ヒーロークラスのインポート)







  import {Hero} from './hero';
      
      





ヒーロープロパティはインバウンドです。







HeroDetailComponent



コンポーネントに表示するヒーローをHeroDetailComponent



する必要があります。 誰が彼にそれを言うのでしょうか? AppComponent



親!







AppComponent



、表示するヒーローを知っています。ユーザーがリストから選択したヒーローです。 ユーザーの選択はselectedHero



プロパティにあります。







AppComponent



テンプレートを更新して、 AppComponent



プロパティをHeroDetailComponent



hero



プロパティにHeroDetailComponent



ます。 バインディングは次のようになります。







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





hero



プロパティがターゲットプロパティであることに注意してください-(=)の左側に角かっこで囲まれています。







Angularでは、宣言されたターゲットプロパティが受信プロパティである必要があります。 そうしないと、Angularはバインドを拒否し、エラーメッセージを表示します。







ここでは、入力プロパティについて詳しく説明します 。また、 ターゲットプロパティにこの特別なアプローチが必要な理由を説明しますが、 ソースプロパティには必要ありません。


hero



インバウンドであることを示す方法はいくつかあります。 先ほどインポートした@Input



デコレータでhero



プロパティに注釈を付けることで、これを優先する方法にします。







  @Input() hero: Hero;
      
      





@Input()



デコレータの詳細については、 属性ディレクティブの章を@Input()





AppComponentの更新



AppComponent



に戻って、彼にHeroDetailComponent



使用方法を教えましょう。







まず、 HeroDetailComponent



をインポートして、参照できるようにします。







  import {HeroDetailComponent} from './hero-detail.component';
      
      





Hero Detailのコンテンツを削除したテンプレート内の場所を見つけ、 HeroDetailComponent



を表す要素タグを追加します。







  <my-hero-detail></my-hero-detail>
      
      





my-hero-detailは、 HeroDetailComponent



メタデータのselector



プロパティで設定した名前です。


次のように、 AppComponent



コンポーネントのselectedHero



プロパティをAppComponent



コンポーネントのhero



プロパティに関連付けるまで、これら2つのコンポーネントは調整されません。







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





AppComponent



テンプレートは次のようになります。

app.component.ts(テンプレート)







  template:` <h1>{{title}}</h1> <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <my-hero-detail [hero]="selectedHero"></my-hero-detail> `,
      
      





バインディングのおかげで、 HeroDetailComponent



AppComponent



からヒーローを受け取り、リストの下にこのヒーローの詳細情報を表示する必要があります。 この情報は、ユーザーが新しいヒーローを選択するたびに更新する必要があります。







これはまだ起こっていません!







ヒーローのリストをクリックします。 情報なし。 「Browser Developer Tools」コンソールでエラーを探しています。 エラーはありません。







Angularは新しいタグを無視しているようです。 これは、彼が新しいタグを本当に無視しているためです。







ディレクティブの配列







ブラウザは、未知のHTMLタグと属性を無視します。 角度も同じです。







HeroDetailComponent



をインポートし、テンプレートで使用しましたが、Angularに通知しませんでした。







directives



配列のメタデータにこのコンポーネントをリストすることで、このAngularについて説明します。 このプロパティの配列を@Component



構成の下部、 template



styles



直後に追加しstyles









  directives: [HeroDetailComponent]
      
      





稼いだ!



ブラウザでアプリケーションを表示すると、ヒーローのリストが表示されます。 ヒーローを選択すると、彼に関する詳細情報が表示されます。







基本的な変更点は、このHeroDetailComponent



コンポーネントを使用して、アプリケーションのどこかでヒーローに関する詳細情報を表示できることです。







最初の再利用可能なコンポーネントを作成しました!







アプリケーション構造の概要



この章でリファクタリングした後、次のプロジェクト構造があることを確認しましょう。







  angular2-tour-of-heroes app app.component.ts hero.ts hero-detail.component.ts main.ts node_modules ... typings ... index.html package.json tsconfig.json typings.json
      
      





この章で説明したコードファイル。







app / hero-detail.component.ts
  import {Component, Input} from 'angular2/core'; import {Hero} from './hero'; @Component({ selector: 'my-hero-detail', template: ` <div *ngIf="hero"> <h2>{{hero.name}} details!</h2> <div><label>id: </label>{{hero.id}}</div> <div> <label>name: </label> <input [(ngModel)]="hero.name" placeholder="name"/> </div> </div> ` }) export class HeroDetailComponent { @Input() hero: Hero; }
      
      





app / app.component.ts
  import {Component} from 'angular2/core'; import {Hero} from './hero'; import {HeroDetailComponent} from './hero-detail.component'; @Component({ selector: 'my-app', template:` <h1>{{title}}</h1> <h2>My Heroes</h2> <ul class="heroes"> <li *ngFor="#hero of heroes" [class.selected]="hero === selectedHero" (click)="onSelect(hero)"> <span class="badge">{{hero.id}}</span> {{hero.name}} </li> </ul> <my-hero-detail [hero]="selectedHero"></my-hero-detail> `, styles:[` .selected { background-color: #CFD8DC !important; color: white; } .heroes { margin: 0 0 2em 0; list-style-type: none; padding: 0; width: 15em; } .heroes li { cursor: pointer; position: relative; left: 0; background-color: #EEE; margin: .5em; padding: .3em 0; height: 1.6em; border-radius: 4px; } .heroes li.selected:hover { background-color: #BBD8DC !important; color: white; } .heroes li:hover { color: #607D8B; background-color: #DDD; left: .1em; } .heroes .text { position: relative; top: -3px; } .heroes .badge { display: inline-block; font-size: small; color: white; padding: 0.8em 0.7em 0 0.7em; background-color: #607D8B; line-height: 1em; position: relative; left: -1px; top: -4px; height: 1.8em; margin-right: .8em; border-radius: 4px 0 0 4px; } `], directives: [HeroDetailComponent] }) export class AppComponent { title = 'Tour of Heroes'; heroes = HEROES; selectedHero: Hero; onSelect(hero: Hero) { this.selectedHero = hero; } } 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" } ];
      
      





アプリ/ hero.ts
  export class Hero { id: number; name: string; }
      
      





歩いた道



作成したものをまとめましょう。









アプリケーションを起動する、パート3







今後のパス



ヒーローツアーは、共有コンポーネントでの再利用に適しています。







AppComponent



ヒーローデータを取得します(スタブを使用して取得します)。 これは最良のオプションではありません。 データへのアクセスをリファクタリングし、別のサービスでデータの受信を取り出し、このデータを必要とするコンポーネントとこのサービスを共有する必要があります。







次の章でサービスの作成方法を学びます。








All Articles