ペロハム大学

ヤルゾー

Angularチュートリアルをやる 6日目

■ 思ったこと

最終章までたどり着いたぞ!!

■ 6. HTTPサービスの有効化

HTTPリクエストを介してHeroServiceがデータを取得できるようにしょう!HTTPを通してデータの保存ができるようになるとな、APIとかのことかね?

HttpClient

HTTPを通してリモートサーバーと通信するための仕組み。app.modual.tsHttpClientModuleをインポートして、imports配列にセットすれば準備はOK

In-memory Web APIをインストールしよう

今回は「In-memory Web API」を使ってリモートサーバーとの通信を再現するぞ、モックサーバーみたいなものだと理解!使うにはnpm install angular-in-memory-web-api --saveでパッケージをインストールしよう

app.module.tsにサービスをimport

  • インストールしたパッケージからHttpClientInMemoryWebApiModuleと、これから作成するクラスInMemoryDataServiceをあらかじめインポートする
  • imports配列にはHttpClientInMemoryWebApiModuleforRoot()をチェーンして、データ取得元となるInMemoryDataServiceを引数に持たせよう
  imports: [
    …
    HttpClientModule,
    HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, { dataEncapsulation: false }),
  ],

InMemoryDataServiceを作るのだ

  • HTTPでデータをやり取りする用のサービスが必要、ng generate service InMemoryDataでサクっと作ろう
  • 大事なのはcreateDb()InMemoryDbServiceを実装するべし
  • heroes.tsで定義していたモックデータをcreateDb()の返り値にすればOK
export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const heroes = [
      { id: 1, name: 'warrior' },
      { id: 2, name: 'thief' },
      { id: 3, name: 'robot' },
      { id: 4, name: 'inventor' },
      { id: 5, name: 'witch' },
      { id: 6, name: 'jester' },
    ];
    return { heroes };
  }

HeroServiceをHTTP対応仕様に変更セヨ

  • まずはconstructorにHttpClientを追加する
  • 次にAPIのURLを定義しよう、createDb()で設定した戻り値heroesがURLとなるぞ!
  • サーバーからデータの取得にはhttp.get()<>を使う、引数に設定したエンドポイントにデータを取りに行ってくれるぞ
  • 今回はof(HEROES)http.get<Hero[]>(this.heroesUrl)に書き換えればOK
  • すべてのHttpClientメソッドはObservableを返すので、戻り値は変わらずObservable<Hero[]>となる

エラーハンドリングも必要だ

  • getHeroes()が失敗することもまぁあるでしょう。失敗したとしても、結果としてObservableが返ってくれば問題ないのでObservable.pipe()を使ってどうにかしよう、pipe=パイプ、複数の機能を一個にまとめられる、便利
  • Observablepipe()で値を加工できる(Promiseのthen的な)
  • 今回はpipe()に失敗したObservable処理用のcatchErrorオペレーターを設定しマス
  • 正常なObservableが返ってくれば処理が続くのでcatchError()の引数にhandleError()を渡してそこで処理してもらおう
getHeroes(): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      catchError(this.handleError<Hero[]>('getHeroes', []))
    );
}

handleError()を作る

  • HeroServiceの中に作るぞ、エラーを直接触る関数だ!
  • 汎用的な処理なので、型引数で取得できなかったデータの型を受け取るようにしよう
  private handleError<T>(operation = 'operation', result?: T) {
    // Observable<Hero[]>を返す正常な関数を返す
    return (error: HttpErrorResponse): Observable<T> => {
      console.error(error);
      this.log(`${operation} failed: ${error.message}`);
      // 空のHero[]を返す
      return of(result as T);
    };
  }
  • consoleの取得結果は「HeroService: getHeroes failed: undefined 」となった

getHeroesをちょこっと改修

  • tapオペレーターを使ってログ出力をまとめちゃお
  • tap()pipe()の中で使える、受け取った関数を実行するだけの関数
  • .pipe()の引数にtap()catchError()二つ入っていますが、順に処理してくれる。オペレーターは組み合わせて使うのだ!
  getHeroes(): Observable<Hero[]> {
    const heroes = this.http.get<Hero[]>(this.heroesUrl).pipe(
      tap(() => this.log(`fetched heroes`)),
      // 戻り値のOperatorFunctionはObservable を返す関数
      catchError(
        // エラー用にメッセージと空配列を渡す
        this.handleError<Hero[]>('getHeroes', [])
      )
    );
    return heroes;
  }

getHeroも同じく修正

  • http.get時に自分のidの画面に渡れるようにしてあげればOK、他はだいたい同じ!
  • ちょっと待って!自分のidっていうけど…エンドポイントのURLにidは含まれていないのですが!!でも大丈夫、:baseURL/:idでidから取得する仕組みがあるみたい
    const url = `${this.heroesUrl}/${id}`;

更新機能を追加する

いまだと、せっかく詳細画面で名前を変えてもGo backすると変更は元に戻ってしまう。変更を永続化するには、サーバーに送り返すべし!というわけで、保存ボタンを追加しよう

hero-detail.componentにsave()を作ろう

コンポーネント鉄の掟、「データの取得や保存は行わぬ」がありますので、ここもサービスを呼んで、保存されたら戻るコールバック関数にする

  save() {
    this.heroService.updateHero(this.hero).subscribe(() => this.goBack());
  }

サービスの中でupdate!

  • http.put()を使う、こいつがサブスクされるとデータが書き換わるとな
  • 引数には「URL」「アップデート用のデータ」「オプション(ヘッダ情報)」を設定する
  • URLはidつけなくてOK、データから特定されるらしい、かしこいねえ
    • これは「Angular in-memory-web-api」の機能で、一意のidがある前提だからみたい
  • ヘッダ情報は新しくnew HttpHeadersしてContent-Typeのみ設定している。どんなデータで送信するか伝えるためにも必要

■ 感想

エラー周りの関数の理解がかなりむずかしかった。いや、全部難しいね、http周りの知識が乏しい!ゴールデンウイークは料理したりしてる、世界樹早くやりたい、と待ってる時間が一番楽しいカモネ

Angularチュートリアルをやる 5日目

■ 思ったこと

次の章に行くごとにわけわからん状態になってその都度勉強していく感じ、ほぼ世界樹の迷宮ですね

■ 5. ルーティングを使ったナビゲーションの追加

Angularルーターを使って画面遷移をやっていこう!

AppRoutingModule

  • ルーティング専用のトップレベルモジュールっていうのがあると良い
  • 慣例でモジュールのクラス名はAppRoutingModuleとなるよ!
  • モジュールはng generate module app-routing --flat --module=appで作る
    • --flat:src/appに生成したファイルを置く
    • ---module=app:AppModuleのimports配列に生成したモジュールを登録する(使うために登録は必須!)
  • が、プロジェクト作成時に自動で作ってたみたいだ、もうあった!
  • routes配列にHeroesComponentのpathとコンポーネント名を設定、こうするとhttp://localhost:4200/heroesが使えるようになる

RouterOutletを使う

AppRoutingModuleで設定したルーティングを設定するには、html上でrouter-outletタグを書いてあげればOK

routerLinkも使う

詳細にどこへ飛ぶか?は<nav>要素の中にaタグ入れてrouterLinkを設定してあげるべし。routerLinkはこれでクリックをルーターのナビゲーションへ変換するセレクタだ。もうコンポーネントを直接書く必要はないぜ!

ダッシュボードビューを追加しよう

  • 正直、ルーティングって複数ページnight意味ないし、も一個ぐらいコンポーネント増やしたいよね?おっしゃる通り、ということでng generate component dashboardをしましょう
  • ダッシュボードビューではヒーロー配列からピックアップしてヒーローを表示する、なのでこちらのコンポーネントにもheroServiceを注入してgetHeroes()を使おう!

デフォルトルート

空パスの場合に自動遷移させるにはAppRoutingModule routes配列に{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },を追加するべし(今回はダッシュボードをデフォルト遷移先にするのだ)

詳細画面を遷移先に変えよう

  • 今はHeroesComponentでヒーロー名クリックしたら下に出る感じですが…いろんなとこから遷移して表示する形に改修しよう
  • heroes.component.htmlbuttonrouterLinkに変更、リンク先はdetailhero.idを足したものとする。idが2としたら、こんな感じになる!例)~/detail/2
  • 選択したheroを元にonSelect()で詳細画面を表示する部分もいらなくなるよ
  • 当然、今のままではリンク先には飛べないが・・??

hero-detail.component.tsの大改修

  • ~/detail/idありきで、idを取得し、そのデータをサービスからGETできるようにしましょう
  • そのためにもconstructorに以下を追加するノダ
    • ActivatedRoute:ルートに関する便利機能を色々持ってるクラス
    • HeroService:おなじみ!サービスからデータをもらおう
    • Location:ブラウザのURLをいい感じにやりとりするサービス、 今回は前のビューに戻るのに使う
  constructor(
    private route: ActivatedRoute,
    private heroService: HeroService,
    private location: Location
  ) {}
  • URLからidを取得するのにrouteが使えるぞ。route.snapshotコンポーネントが作成されたときのルート情報を取得しよう!スクショのURLはhttp://localhost:4200/detail/1
  • ルートパラメータは文字列なので、Numberでキャストを忘れずに
  • idが特定出来たらいつも通りサービスから取得すればOK
  getHero() {
    const id = Number(this.route.snapshot.paramMap.get('id'));
    this.heroService.getHero(id).subscribe((hero) => (this.hero = hero));
  }
  • ちなみに、修正前は親コンポーネントからheroがバインディングされていたが…今の詳細コンポーネントは親から独立しているので@Input hero?: Hero;から@Inputは不要になる
  • getHero()HeroServiceがないのでこの時点ではエラーになるぞ、早急にHeroService.getHero()を追加するのだ!

戻るボタンの追加

  • 詳細画面からまえのがめんにもどれなくっちゃね、hero-detail.component.htmlに戻るボタンを追加しよう!
  • クリック時のイベントにはgoBack()を追加してhero-detail.component.tsに実装しよう
  • location.back()を使えばよいです

■ 感想

くっついてるコンポーネントはなるべくマルっくとホドホドにホドいてイェ~そどってねツァク。

Angularチュートリアルをやる 4日目

■ 思ったこと

実生活がしんどすぎてきしめんで泣く!

■ 4. サービスの追加(2)

こっから難しいが、Promiseを乗り越えた今ならば!!

非同期処理にしてみよう

  • 前回heroService.getHeroes()でヒーローを取得しましたが、これは同期的な処理ですので汎用的ではありません。非同期処理として実装してみるべし!
  • 最終的にheroService.getHeroes()したらObservableが返ってくれば正解だ!ObservableはRxJSライブラリで重要なクラス、いや、何が何の何!?

RxJSライブラリとは

  • 非同期処理を実装するためのライブラリ
  • Observable型の実装を提供している

Observableってなによぉ・・!!

  • RxJSの基本的なオブジェクトのことだっ!
  • Observableした関数はConsumer(使う側?)がsubscribe(購読)するまでは実行されない
  • サブスクするConsumerはその処理が完了orサブスク中止するまで状態の変化を通知として受け取れるらすぃ
  • Observableによって公開された値をストリームと呼ぶ
  • サブスクされる前に、ストリームを操作できるオペレーター関数がある
    • 例)of()、map()、filter()、concat()、flatMap()
  • サブスク自体はsubscribe()で呼び出せマス

Observable HeroServiceにしてみよう

  • Observableする関数はgetHeroes()、戻り値をObservable型に書き換えるのだ
  • ストリームをそのままキャッチするにはof()を使おう
    • ofはデータを特に加工せず、そのまま取得するオペレーター
  • 戻り値はHero[]からObservable<Hero[]>となる

HeroesComponentでSubscribe!

  • 戻り値が変わりましたので、getHeroesを使ってるコンポーネントも当然修正が必要になる
  • Observableした関数が処理を終えるまで待ってあげられるようにしよう!
  • 対象メソッドに.subscribe()をチェーンして、その中で引数を変数にセットできるコールバック関数を書いてあげればいーのだ

それはそうと、データ取得成功時にメッセージ出してみようぜ

  • 例によってng generate component messagesでMessagesComponent を作成します
  • app.component.htmlで呼び出してあげれば準備はOK!
  • 次に、MessageService もng generate service message作ったろう
  • message.service内にはmessages変数と add()clear()をrootで作成するのだ

サービス内でサービスを利用する

  • 今作ったmessageServiceHeroServiceに注入する
  • 注入のやり方は覚えているか??コンストラクタに追加して引数に入れるだったね、サービスクラスでもおんなじ!
  • おめでとう、HeroService内でmessageServiceのメソッドおよび変数も使えるようになったぞ!
export class HeroService {
  // サービス内でサービスを利用する
  constructor(private messageService: MessageService) {}

  getHeroes(): Observable<Hero[]> {
    const heroes = of(HEROS);
    this.messageService.add('HeroService: fetched heroes');
    return heroes;
  }
}

HeroesComponentでもmessageServiceを利用する

  • 同じく注入したげればOKなのよ
  • クリック時に動く関数onSelect内でaddするようにしました。これでクリックした結果をメッセージ配列に貯めて画面に出せるようになったってワケ

■ 感想

ゴールデンウイークなのでどんどん進めたいですね・・・・

Angularチュートリアルをやる 3日目

■ 思ったこと

4年前ぐらいに買いっぱなしだった書籍「Angularアプリケーションプログラミング」を辞書のように使っていく!

【番外編】 Angularの概念

いまさらだが、やっぱこっからちゃんと見た方がいいよね(Angular 日本語ドキュメンテーション

Angularとは

  • HTMLとTypeScriptでSPA(=シングルページクライアントアプリケーション)を開発するためのフレームワーク
  • 基本的な構成要素は、 NgModule で組織されたAngularコンポーネント・・NgModule ??

NgModule!?

  • @NgModuleデコレーターを付与されたクラスのこと
  • モジュールとは、Angularアプリを構成する部品(コンポーネント、サービス、ディレクティブ、パイプなど)をまとめた単位のこと
  • Angularアプリは最低一個のモジュールが必要
  • 起動時に呼ばれるのがルートモジュール(またはメインモジュール)
  • とりあえずNgModule をインポートして@NgModuleデコレーターで構成情報を付与すれば君も今日からモジュールだ!

Angularアプリケーションとは

  • 常に1つの ルートモジュールと多くの 機能モジュール で構成されたもの!

デコレーター (@)

  • Angularに構成情報を教えてあげるもの
  • モジュール、コンポーネントやサービスなどのクラスに付与して使う

コンポーネント

  • ページを構成するUI部品をまとめた単位のこと
  • 起動時に呼ばれるのがルートコンポーネント(またはメインコンポーネント
  • Componentをインポートして@Componentデコレーターで構成情報(紐づくビューとか)を付与すればよい
  • コンポーネントで使用したいデータはサービスから注入される

サービス

  • コンポーネント間で共有したいデータやロジックを設定するクラス
  • サービスクラスには@Injectable()デコレーターを付与して共有したいメソッドを定義する
  • これのいいところですが、コンポーネントがサービスクラスを実体化してインスタンス化…とかしなくても、サービスクラス使う宣言すればインスタンス化し放題なところです!
  • そこら辺の仕組みはDIコンテナってやつがうまくやってくれている
  • 依存関係(Dependency)の注入(injetion)なのでDI

■ 4. サービスの追加

今は配列にいろいろ直書きした仮データを表示しているが、この章ではモックサービスを利用していい感じにするらしい。

そもそもコンポーネント内では

データの取得や保存は行わぬ、コンポーネントはデータの受け渡しに専念せねばならぬのだ。なので、その他の処理はServiceクラスに任せよう!!

HeroServiceを作成しよう

ng generate service heroってやるとまたも良い感じにファイルが作成される。src/appの直下に出来るのがちょっとイヤ!今度はCREATE のみのようだ。

CREATE src/app/hero.service.spec.ts (347 bytes)
CREATE src/app/hero.service.ts (133 bytes)

生成されたhero.service.ts@Injectable()があらかじめ付与されていた、()の中に構成情報が書かれている。 デフォルトでprovidedIn: 'root'となっているが、ここでは依存性の注入方法を宣言しており、ルート指定するとアプリケーション全体で使用できるみたい…むしろ、こうしないと使えないぜ!

データの取得

  • データは例えばAPI、ローカルストレージ、モックデータなど色んなとこからやってくるが、サービスに取得ロジックを書いてあげればコンポーネントはただ受け取り屋さんになれるので便利!
  • 今回は引き続きモックデータを使うので、HEROESをインポートし、取ってきた結果を入れるようの配列も必要なのでHeroもインポートする
  • あとはgetメソッドつくればOK!
  getHeroes(): Hero[] {
    return HEROS;
  }

HeroesComponent の更新

  • 上記の通りコンポーネントで直接データを取得する必要はないため、「2. リストの表示>ヒーローのモックを作成」で作ったモッククラスのインポートは削除する
  • そんで、今作ったサービスをインポートする!
  • Heroクラスはインポート済なので、もらったデータをheroesに設定できるように書き換える
  • このままではサービスはまだ使えない、サービスの注入を行おう
  • コンストラクタを追加して、引数にHeroServiceを渡してあげればOK
 constructor(private heroService: HeroService) {}

HeroesComponentでデータをゲット

  • するには、注入されたサービスのgetメソッドを使いましょう
// サービスからheroesを取得
  getHeros() {
    this.heroes = this.heroService.getHeroes();
  }
  • getメソッドはngOnInit()というメソッドで呼び出して使う、コンストラクタは使わないのか?オーキドのことば、ものにはつかいどころがあるんじゃ…!

ngOnInit()

  ngOnInit(){
    this.getHeros();
  }
  • ここまでやれば、画面が動く!

いったん整理

  • src/app
    • app.component
    • app.module
      • ルートモジュール
    • hero.service
      • サービスクラス、今回はモックデータゲットに使う
    • hero
      • Hero型
    • mock-heros
      • モックデータ入りのHero型配列
  • src/app/heroes
  • src/app/hero-detail
    • hero-detail.component
      • heroesから詳細画面を分割したもの

■ 感想

DI完全に理解した!!

Angularチュートリアルをやる 2日目

■ 思ったこと

バインドって聞くとサバクのネズミ団を思い出す!ということでチュートリアル続き

2. リストの表示

ヒーローのモックを作成

  • 表示用にモックデータを作るノダ、さっき作ったHeroクラスをインポートしてその型を基に配列を作ろう
  • heroes.component.tsにプロパティを定義すればすぐにhtmlでバインディング

反復ディレクティブ

  • for文的なやつ、*ngForをタグに埋め込むとそいつが繰り返して表示される
  • ディレクティブはhtml内で使えるカスタム属性
<li *ngFor="let hero of heroes">

ディレクティブもうちょっと詳しく

クリックイベントもバインディング

  • 今リストをボタンで作成してるんだけど、それらのクリックイベントを作ろうという話
  • これはイベントバインディングを使いますね間違いない…ということで、htmlのbuttonに(event) = "handler"構文を埋め込むノダ
    <button
      [class.selected]="hero === selectedHero"
      type="button"
      (click)="onSelect(hero)"
    >
  • handlerはts側に作成しよう
  selectedHero?: Hero;
  // 送られてきたheroをselectedHeroに格納
  onSelect(hero: Hero): void {
    this.selectedHero = hero;
  }

ngIfで詳細を出してみる

  • せっかくクリックしたヒーローを取得できるようになったので、使ってみよう
  • 今回は<div *ngIf="selectedHero"><div>で、selectedHeroが取得されてるときのみヒーローの詳細を表示するよーにした
    • 要するにクリックされたときってこったね!

クリックされたボタンを分かりやすくする

  • ボタンがクリックされた時だけCSSを追加してあげればよい
  • [class.selected]="hero === selectedHero"でtrueの時だけCSSselectedCSSが追加されマス、YES属性バインディング
.heroes button:selected{
  background-color: #505050;
  color: white;
}

3. フィーチャーコンポーネントの作成

てな感じで今は一覧と詳細が一個のコンポーネントに書かれている感じだが、、こんなん分割するに越したことがないぜ! ということでまずはng generate component hero-detailで新たなコンポーネントを作りました。例によって@NgModuleに追記も増えていた。確かに実行時のログ見たらUPDATE されてあったわ

CREATE src/app/hero-detail/hero-detail.component.html (26 bytes)
CREATE src/app/hero-detail/hero-detail.component.spec.ts (628 bytes)
CREATE src/app/hero-detail/hero-detail.component.ts (221 bytes)
CREATE src/app/hero-detail/hero-detail.component.css (0 bytes)
UPDATE src/app/app.module.ts (607 bytes)

htmlの分割

  • heroes.component.htmlからhero-detail.component.htmlに詳細部分を持ってきました
  • もとは*ngIf="selectedHero"だったけど、詳細コンポーネントは受け取ったheroをただ表示すればいーので<div *ngIf="hero">に書き換える
  • しかし、Hero型がtsファイルにインポートされてないからエラー出るぞ!次!

コンポーネントで@Input()

  • hero-detail.component.tsは外部からデータを受け取る身、子コンポーネントだったのだ
  • それゆえ、ただHero型をインポートすればいいだけではなかった。データ受け取ります!宣言しなきゃいけないらしい
  • というわけなので、heroを使いたいなら、@Input() hero?: Heroと書こう

コンポーネントはhtmlで プロパティバインディング

  • こういうことだ!
<!--
HeroesComponent.selectedHero → ターゲット要素.hero
への単方向データバインディング
-->
<app-hero-detail [hero]="selectedHero"></app-hero-detail>

■ 感想

専門用語が難しいのでその都度調べてやるしかない!次の章から一気にレベルアップする気がするぜ!

Angularチュートリアルをやる 1日目

■ 思ったこと

まずは公式みながら環境設定→ワークスペースの作成→チュートリアルまでやろうと思うhttps://angular.jp/guide/setup-local#angular-cliをインストールする-

■ Angularをはじめよう

下準備

なになに、ローカルシステムにAngularをインストールするには、Node.jsnpmが使える必要とな……ある!!OK!!

Angular CLIをインストール

Angular開発で必須なコマンドラインツールのこと、コマンドプロンプトnpm install -g @angular/cliでインストールできる、ng versionでversion確認まで出来たらOK!ng なんちゃらって感じで使えるよ

ワークスペース作ってみる

VSCodeのターミナルでng new my-appしました。全部入りのひな形プロジェクトが作られるみたい、npmインストールも兼ねている。成功するとこんな感じ

実行してみる

cd my-appしてng serve --openするとhttp://localhost:4200/が立ち上がって画面が開く!これでとりあえずの動作確認はいいか

チュートリアルやり申す

https://angular.jp/tutorial/tour-of-heroes/toh-pt0ツアー・オブ・ヒーローズ……?

1. ヒーローエディター

アプリケーションシェル

画面開いた時に表示されたページ、それがアプリケーションシェルらしい。こいつはAppComponentと名の付く三つのコンポーネントから成り立つぞ、src/appに行ってみよお!

  • app.component.ts
    • TypeScriptで書かれたコンポーネントクラスのコード
    • AppComponentクラスがすでにできているが、ここのtitleプロパティを書き換えてあげると、htmlで{{}}バインディングされた対応箇所も変わる仕組み。だからexport されてるんですね
  • app.component.html
    • HTMLで書かれたコンポーネントのテンプレート
    • 上で先に言ったけど・・{{}}は補間バインディングという構文、tsでどんどんプロパティ作ってhtmlに埋め込んでいくイメージか
  • app.component.css
    • そのまんま、CSS

コンポーネントを作る

ng generate component heroesってやると、src/app/heroes/ごとまるっとコンポーネントが作成される!こりゃあ便利だね。中身はやっぱりtsとhtml,css

Componentシンボル

  • 生成したtsファイルにはデフォルトでComponentがインポートされていたが、クラスに@Componentもくっついているはず
  • こいつはデコレーターつって、クラスにメタデータを付与してくれていたのだ
  • メタデータはとりあえず、クラスに設定必要な情報と理解しておこう)
  • ng generateが生成してくれたものは3つのメタデータプロパティでした
  • こうしてみると、確かに自動生成されているとありがたい

インターフェースを作成する

  • おさらいすると、インターフェースはオブジェクト型に型名つけるやつ!
  • heroesクラスにこれからHeroを生成していくわけだけど…src/appに自分でhero.ts作って、そこにHeroインターフェースを作成しとこうって話
  • 作ったオブジェクトはhtml内に{{selector.プロパティ名}}バインディングすべし

双方向データバインディング

  • チュートリアルいわく、htmlから入力した値をプロパティに流し込んだら素敵やん、ということで[(ngModel)]というものがあるらしい
  • 双方向に データを流すから、双方向データバインディング
<input id="hero-name" [(ngModel)]="hero.name" placeholder="name" />
  • placeholderはhtmlで使える属性、初期値を設定できるぜ

ていうか…データバインディングについてもっと詳しく!

AppModule

  • ngModelを使うにはFormsModuleのインポートが必要
  • インポート先はAppModule!Angular全体としてどーいう部品使う?みんなファイルやライブラリ何使ってるの?…いわゆるメタデータ!こゆのを知っておく場所
  • だいたいメタデータ@Componentで個別に付与されてるけど、その他重要なものはAppModuleの@NgModuleに含まれている
  • ということで、ここにインポートして@NgModuleimports配列に追記してあげればOK
    • アプリケーションに必要な外部モジュールのリストだよ
  • これに限らず、すべてのコンポーネントNgModuleで宣言されていなければならない
  • 実際、さっき作ったHeroesComponentもいつの間にdeclarations配列に含まれている
    • ng generateしたときに自動で書きこんでくれてたんだね…!ありがとう、CLI

■ 感想

手でコンポーネント作ったらそれなりに事故が起きそうだ、ありがとうCLIチュートリアルの文章がユーモアあって結構おもしろい、いいね!!でも、細かい仕組みとかはよくわからんので・・まずは手を動かして、そのあと改めて勉強も必要そうな!

プロを目指す人のためのTypeScript入門 読書メモ⑭ 第8章(3)

■ 思ったこと

早くAngularのチュートリアルやりたいぜ…

■ 第8章 非同期処理(8.4~8.5.4)

  • 前回まではthenで処理を動かしていたが、実際はもっと使われる書き方があるらしい

ちょっとおさらい

  • Promiseみたいに書くけど、Promiseオブジェクトってどういうもんなの
  • なんも入ってなければこんな感じPromise { <pending> }
  • 例のようにnumber入れたらこんな感じで返ってくるよPromise { 100 }
  • だから型引数が必須なのですね!

async関数

  • functionの前にasyncをつけるasync function構文から始まるぞ
  • アローで書くならconst main = async () => { 処理 }って感じ
  • 返り値は必ずPromise!だから中身を使いたいなら返り値.then()
    • こんな感じで使えるconst result = 返り値.then((変数) => {なんか処理})

await式

  • async関数の中で使える構文!
  • awaitを使うとasync関数の実行が一時中断する
  • awaitがくっつく式はPromiseオブジェクト、Promiseの結果が出るまで待ってくれるのさ
// await実行されたら解決するまで中断する
async function getNumber() {
  try {
    console.log(`getNumber staert`);
    await sleep(1000);
    console.log(`getNumber end`);
    return 30;
  } catch {
    console.log(`失敗!`);
  }
}

console.log(`実行!`);
getNumber().then((num) => {
  console.log(`getしたNumberは${num}`);
});

// awaitを待ってる間外の関数は普通に進む
console.log(`待機中~`);

//[console]
// 実行!
// getNumber staert
// 待機中~
// getNumber end
// getしたNumberは30

■ 感想

難しいが、だいたいは、、前よりはOK!後輩に説明できるかというと、、??!次の9章はコンパイラオプションはさらっと読んだので、またプロジェクト1から作るときに熟読します!ということでここで一区切り!!基本的なことが学べたというか、TypeScriptに慣れることができたって感じ!!土台作りとしてほんとにわかりやすかった!!!ありがとうございます!!!!