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あり、新しいHeroDetailComponenthero-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プロパティがあります。 したがって、新しいテンプレート全体でselectedHerohero置き換えます。 これが唯一の変更です。 結果は次のようになります。


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> `, 

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


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


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


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


ディレクティブの配列


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


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


directives配列のメタデータにこのコンポーネントをリストすることで、このAngularについて説明します。 このプロパティの配列を@Component構成の下部、 templatestyles直後に追加し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ヒーローデータを取得します(スタブを使用して取得します)。 これは最良のオプションではありません。 データへのアクセスをリファクタリングし、別のサービスでデータの受信を取り出し、このデータを必要とするコンポーネントとこのサービスを共有する必要があります。


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



Source: https://habr.com/ru/post/J282634/


All Articles