LoginSignup
1
1

More than 1 year has passed since last update.

Angularの公式チュートリアルをやるついでに、ホットリロードやMVVMなども学ぶ。

Last updated at Posted at 2022-11-04

はじめに

前回の記事では、Angular on Docker環境を構築した。
アプリケーション名は sample-angular-on-docker という事にしている。

今回は、Angular公式チュートリアルのうち、『チュートリアル: Tour of Heroes』を実施する。
本チュートリアルは、以下の章立てで進められる。

  • イントロダクション
  • プロジェクトの作成
  • 1.ヒーローエディター
  • 2.リストの表示
  • 3.フィーチャーコンポーネントの作成
  • 4.サービスの追加
  • 5.ナビゲーションの追加
  • 6.サーバーからデータの取得

基本的にチュートリアルに沿っていくので、写経的な記事を書かず、
各章で詰まった点や、押さえておきたいポイントについて記事として残していく。

各種ポイント

本記事のタイトルの通り、チュートリアルをやるついでに色々と学んでいく。
ポイントとしては以下の通り。

  • [POINT] ホットリロード
  • [POINT] ディレクトリ構成
  • [POINT] 「spec」って何?
  • [POINT] componentservice の違い
  • [POINT] その他

[POINT] ホットリロード

ファイル更新時にホットリロードしてくれると嬉しいなと思って調べてみると、起動オプションに --poll を設定してあげればよいとの事。
なので、起動時に以下を使うようにする。

sh
# こっちじゃなくて
root@60ff460a2f75:/projects/app# ng serve --host 0.0.0.0

# こっちを使う事で、ホットリロードができる
root@60ff460a2f75:/projects/app# ng serve --host 0.0.0.0 --poll 1  # 起動オプション --poll を指定

[POINT] ディレクトリ構成

ディレクトリ構成(プロジェクト作成直後)

プロジェクト作成直後のディレクトリ構成は以下の通り。

プロジェクト作成直後のディレクトリ構成
sh
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
|   └── (割愛)
├── node_modules
|   └── (割愛)
└── src
     ├── app
     │   ├── app-routing.module.ts
     │   ├── app.component.css
     │   ├── app.component.html
     │   ├── app.component.spec.ts
     │   ├── app.component.ts
     │   └── app.module.ts
     ├── assets
     ├── environments
     │   ├── environment.prod.ts
     │   └── environment.ts
     ├── favicon.ico
     ├── index.html
     ├── main.ts
     ├── polyfills.ts
     ├── styles.css
     └── test.ts

ディレクトリ構成(チュートリアル完了直後)

チュートリアルを進めていくと分かるが、 componentservice などをAngular CLIで実行するたびに、 app/ 配下に乱雑にファイルが生成される。

チュートリアル完了直後のディレクトリ構成
sh
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
|   └── (割愛)
├── node_modules
|   └── (割愛)
└── src
     ├── app                <---------------------------- app配下が凄い事に!これじゃ管理できないよ X-(
     │   ├── dashboard
     │   │   ├── dashboard.component.css
     │   │   ├── dashboard.component.html
     │   │   ├── dashboard.component.spec.ts
     │   │   └── dashboard.component.ts
     │   ├── hero-detail
     │   │   ├── hero-detail.component.css
     │   │   ├── hero-detail.component.html
     │   │   ├── hero-detail.component.spec.ts
     │   │   └── hero-detail.component.ts
     │   ├── hero-search
     │   │   ├── hero-search.component.css
     │   │   ├── hero-search.component.html
     │   │   ├── hero-search.component.spec.ts
     │   │   └── hero-search.component.ts
     │   ├── heroes
     │   │   ├── heroes.component.css
     │   │   ├── heroes.component.html
     │   │   ├── heroes.component.spec.ts
     │   │   └── heroes.component.ts
     │   ├── messages
     │   │   ├── messages.component.css
     │   │   ├── messages.component.html
     │   │   ├── messages.component.spec.ts
     │   │   └── messages.component.ts
     │   ├── app-routing.module.ts
     │   ├── app.component.css
     │   ├── app.component.html
     │   ├── app.component.spec.ts
     │   ├── app.component.ts
     │   ├── app.module.ts
     │   ├── hero.service.spec.ts
     │   ├── hero.service.ts
     │   ├── hero.ts
     │   ├── in-memory-data.service.spec.ts
     │   ├── in-memory-data.service.ts
     │   ├── message.service.spec.ts
     │   ├── message.service.ts
     │   └── mock-heroes.ts
     ├── assets
     ├── environments
     │   ├── environment.prod.ts
     │   └── environment.ts
     ├── favicon.ico
     ├── index.html
     ├── main.ts
     ├── polyfills.ts
     ├── styles.css
     └── test.ts

ディレクトリ構成(MVVM/最終形)

ソース管理していく上でディレクトリ構成は重要だが、ベストプラクティスが存在しない。
ググってみると、以下のような記事が見つかる。

「ドメイン単位」や「タイプ単位」で分けるように書かれているが、チュートリアルの時点だとそんなものは存在しない。
(いや、存在はしているんだけども、考えたくない)

AngularはMVVMアーキテクチャで構成されるので、そのままディレクトリにしてしまえばよいのでは?
という事で、MVVMに基づいてディレクトリを構成した。

MVVMで再構成したディレクトリ構成
sh
.
├── README.md
├── angular.json
├── karma.conf.js
├── package-lock.json
├── package.json
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
├── .browserslistrc
├── .editorconfig
├── .gitignore
├── .vscode
|   └── (割愛)
├── node_modules
|   └── (割愛)
└── src
     ├── app                <---------------------------- だいぶ役割が分かりやすくなった :-)
     │   ├── app-routing.module.ts
     │   ├── app.module.ts
     │   ├── view
     │   │   ├── app.component.css
     │   │   ├── app.component.html
     │   │   ├── app.component.spec.ts
     │   │   ├── app.component.ts
     │   │   ├── dashboard
     │   │   │   ├── dashboard.component.css
     │   │   │   ├── dashboard.component.html
     │   │   │   ├── dashboard.component.spec.ts
     │   │   │   └── dashboard.component.ts
     │   │   ├── hero-detail
     │   │   │   ├── hero-detail.component.css
     │   │   │   ├── hero-detail.component.html
     │   │   │   ├── hero-detail.component.spec.ts
     │   │   │   └── hero-detail.component.ts
     │   │   ├── hero-search
     │   │   │   ├── hero-search.component.css
     │   │   │   ├── hero-search.component.html
     │   │   │   ├── hero-search.component.spec.ts
     │   │   │   └── hero-search.component.ts
     │   │   ├── heroes
     │   │   │   ├── heroes.component.css
     │   │   │   ├── heroes.component.html
     │   │   │   ├── heroes.component.spec.ts
     │   │   │   └── heroes.component.ts
     │   │   └── messages
     │   │       ├── messages.component.css
     │   │       ├── messages.component.html
     │   │       ├── messages.component.spec.ts
     │   │       └── messages.component.ts
     │   ├── viewmodel
     │   │  ├── hero.service.spec.ts
     │   │  ├── hero.service.ts
     │   │  ├── in-memory-data.service.spec.ts
     │   │  ├── in-memory-data.service.ts
     │   │  ├── message.service.spec.ts
     │   │  └── message.service.ts
     │   └── model
     │        ├── hero.ts
     │        └── mock-heroes.ts
     ├── assets
     ├── environments
     │   ├── environment.prod.ts
     │   └── environment.ts
     ├── favicon.ico
     ├── index.html
     ├── main.ts
     ├── polyfills.ts
     ├── styles.css
     └── test.ts

ちなみに、Angular CLIで componentservice を作ると app/ 配下に作られてしまうが、コマンド実行時にフォルダを作る事も可能。
なので、Angular CLIベースでコードをメンテナンスしていく際には、ディレクトリ構成を決めた上で、実行コマンドに制約をつけて運用するとよいと思う。

sh
# これだと app/ 配下に作られるので、管理しづらい
root@c773d67c1823:/projects/app# ng generate component heroes

# これだと app/view/ 配下に作られるので、管理しやすくなる
root@c773d67c1823:/projects/app# ng generate component view/heroes

[POINT] 「spec」って何?

componentservice をAngular CLIから生成すると、 xxxx.component.spec.ts なるファイルが生成される。

sh
# component の生成
root@c773d67c1823:/projects/app# ng generate component heroes
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.

CREATE src/app/heroes/heroes.component.css (0 bytes)
CREATE src/app/heroes/heroes.component.html (21 bytes)
CREATE src/app/heroes/heroes.component.spec.ts (599 bytes)    <---------- なにこれ!!!!!!!!!!!!!!
CREATE src/app/heroes/heroes.component.ts (275 bytes)
UPDATE src/app/app.module.ts (475 bytes)

# service の生成
root@c773d67c1823:/projects/app# ng generate service hero
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.

CREATE src/app/hero.service.spec.ts (347 bytes)    <---------- なにこれ!!!!!!!!!!!!!!
CREATE src/app/hero.service.ts (133 bytes)

この xxxx.component.spec.ts はチュートリアル内では使用しない。
使用しないからこそ、何のために生成されているのか意味が分からない。

調べてみると、単体試験実行用のファイルらしい。
以下、公式サイト。

[POINT] componentservice の違い

先ほどから componentservice という単語を乱用していたが、そもそもこれらがよく分からない。

調べてみると、公式サイトに以下の記載があった。
以下、公式サイト。

コンポーネントは ビュー を定義します。
ビューは、プログラムのロジックとデータの中からAngularが選択し、変更できる画面要素のセットです。すべてのアプリケーションには、少なくともルートコンポーネントがあります。

コンポーネントは、ビューに直接関係しない特定の機能を提供する サービス を使用します。
サービスプロバイダーは、 依存性 としてコンポーネントに 注入 することができ、コードをモジュール化し、再利用可能で効率的にします。

なるほど。ここでMVVMの観点が生きてくる。
サービスがコンポーネントに注入するという事は、これがデータバインディングの仕組みなのだろうと思う。

なので、コンポーネントは View であり、サービスは ViewModel に相当する事が分かる。

ViewViewModel は分かったけど、 Model は?

Model に相当するものは、おそらく ng generate interface {name} で生成されるものと思われる。
チュートリアル内だと hero.ts がそれに相当するが、コマンドではなく直接ファイルを作成するため、MVVM的観点だと分かりづらい。

試しに上記のコマンドを実行すると、以下のようにファイルが生成される。
hero.ts と同じ構成なので、これが Model なんだと思う。)

sh
# interface の生成
root@c773d67c1823:/projects/app# ng generate interface model/dummy
Node.js version v19.0.0 detected.
Odd numbered Node.js versions will not enter LTS status and should not be used for production. For more information, please see https://nodejs.org/en/about/releases/.
CREATE src/app/model/dummy.ts (27 bytes)

# ファイルの確認
root@c773d67c1823:/projects/app# cat src/app/model/dummy.ts
export interface Dummy {
}

[POINT] その他

他にも、チュートリアルを進めていく上で、表面上の理解しかできず、使い方がいまいちピンと来ないものがあった。
まあ開発を進めていくうちに慣れていくだろうから、今は「こういうのがあるんだな」程度に留めておく。

  • データバインディングには ngModel を用いる
  • classバインディングは、以下を参照
  • *ngFor*ngIf で html を操作
  • ルーティングは ./app/app-routing.module.ts で行われて、 <router-outlet> を使う

チュートリアルを終えて

どうやって構築していくのかは分かったけど、肝心の仕組みだとが概念だとか規約だとかはチュートリアルでは身につかない。
ので、公式サイトの以下を参考に、勉強を進めていく。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1