vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

雑に Angular 再入門(Tour of Heroes App) 1

はじめに

色々あったりなかったりして、 Angular をもう一度触ってみることにしました。

Angular 2 の時代にハンズオンに参加したとはいえ、あれからずいぶん経っているわけなので、もう一度一からやってみるぞい!と思ってサイトを確認したところ、 Angular 8 の今も Tour of Heroes App は現役のようです。

(GETTING START が別にあるのですが、こちらはあらかじめ用意された環境を触ってみる、という感じだったので後にまわすことにしました)

ということで、気になるところは寄り道しつつツアーにお出かけしてみることにします。

準備

まずは準備から。

といっても TypeScript 触っていた影響から Node.js の環境はそろっているため、必要なものは Angular CLI だけです。

npm install -g @angular/cli

VS Code拡張機能としては Angular Language Service だけ入れてみました。

で、プロジェクトを作成します。

ng new angular-tour-of-heroes
cd angular-tour-of-heroes

※本当は ng-sample のような雑な名前にしていましたが、とりあえず合わせてみました。

Error

複数台で試したのですが、以前入れていたものが悪かったのか、 ng new の途中でパーミッションがないとエラーになりました。

が、 npm -g update のあと Angular CLI をインストールしなおしたら直りました。

Angular routing、CSS Framework

ng new を実行すると、 Angular routing を追加するかと CSS Framework を使うかを聞かれます。

  • CSS
  • SCSS
  • Sass
  • Less
  • Stylus

今回はルーティングはツアー中に追加するため追加せず、 CSS もサンプルコードに合わせて素の CSS を選択しました。

以前 PostCSS を使いましたが、 CSS Framework も近いうちに試したいところ。

実行してみる

とりあえず実行してみます。

ng serve --open

--open をつけることで、起動後に Web ブラウザでページを開いてくれます。便利!

...は良いのですが、

f:id:mslGt:20191009190554j:plain

Oh... ナンデコンナニゴウカナノ?

レスポンシブデザインにもなっているという気の利きよう。

どこかの Web Framework を思い出しました。

Empty テンプレートのようなものはあるのでしょうか。

空のページを作る

とりあえず今回は手動で空のページを作ってみます。

とはいえ、実は変更が必要なファイルは一つだけです。

  • src > app > app.component.html

CSS も含め先ほど表示された内容はすべて HTML ファイルに書かれているため、(若干の罪悪感はありつつも)丸ごと削除してやれば空のページが出来上がります。

まぁテスト( app.component.spec.ts )は失敗するようになるわけですが、一旦放置の方向で。

ともあれ、さっそく順番に進めていきますよ。

Directive って何

Introduction の、このチュートリアルを通してできるようになることの中に下記があります。

Angular のビルトインの Directive を使ってヒーローリストの要素を表示・非表示する

...Directive ってナンデスカ?

Angular.js のドキュメントでは

Angular のドキュメントでは Directive 自体についての説明が見つからず、 Angular.js 時代のドキュメントでは、DOM 要素に Angular 特有のふるまいを持たせるためのマーカー、となっていました(と認識)。

@Directive の説明に DOM 要素にカスタムのふるまいを持たせるのに @Directive が使える、というような説明があるため、 Directive の役割自体はあまり変わっていないのだと思われます。

あまり深入りしてもアレなので話を次に進めますが、 Directive には大きく3種類あります。

なぜ Component だけ Component "directive" でないのか、という疑問もありますが、それは置いといて、 Component から順に調べてみますよ。

Component

この 3 種類の中で最も頻繁に使用される Component 。

上記 Getting Started に出てくるもののことを指しているのだとすると、 ng generate component {Component 名} で生成される、下記 3 つのファイルからなる Component となります。
(テストファイルである heroes.component.spec.ts も生成されますが、 Component としては含まれないようです)

ng generate component heroes の場合

  • Component class (heroes.component.ts)
  • HTML template (heroes.component.html)
  • Component-specific styles (heroes.component.css)

まどろっこしい言い方をしているのは、 Component class の中に下記があるためです。

heroes.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
    ~省略~
}

どっちを指しているのか迷うところですが、前者は app.module.ts の @NgModule > declarations に Component class が定義され、ベースとなる HTML (app.component.html) に < app-heroes>< /app-heroes> が追加されることで動作します。

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { HeroesComponent } from './heroes/heroes.component';

@NgModule({
  declarations: [
    AppComponent,
    HeroesComponent,
  ],
~省略~

app.component.html

< h1>{{title}}< /h1>
< app-heroes>

強引に .NET に例えるならば下記のようになるでしょうか。

  • Component class -> コードビハインド
  • HTML template -> XAML
  • Component-specific styles -> デザインファイル

先ほどの Directive の役割が DOM 要素に Angular 特有のふるまいを持たせる、というところから見れば、やはり前者を指していると考えてよさそうです。
(間違ってたら訂正します)

Component-specific styles

とりあえず知りたいことは山ほどあるわけですが、比較的簡単に確認できそうなところから。

ページ全体に影響するようなスタイルは styles.css に書きますが、特定の Component のみに影響するようなものは Component-specific styles に書くと。

最終的には HTML として出力するわけですが、その上で他の Component に影響しないようにする方法とは? と思ったので、とりあえず試してみました。

heroes.component.css

.heroes {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
}

app.component.html

< app-heroes>
< div class="heroes">hello< /div>

こうするとどうなるか。

heroes.component.cssheroes クラスは、下記のように変換されます。

.heroes[ _ngcontent-vyr-c1] {
    margin: 0 0 2em 0;
    list-style-type: none;
    padding: 0;
    width: 15em;
}

そして app-heroes 以下の要素は(例えば div があったとすると)下記のようになります。

< app-heroes>
    < div _ngcontent-vyr-c1>hello< /div>

で、 app.component.html に書いた div はこうなると。

< div _ngcontent-vyr-c0>hello< /div>

ということで CSS のクラス名が異なるため適用されない、と。

なるほどねぇ~。

一旦切ります。

(まぁこういうことしているから終わらないんだよねぇ~。楽しいから良いのだけれども)