はじめに
色々あったりなかったりして、 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 ブラウザでページを開いてくれます。便利!
...は良いのですが、
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
- Structural directives
Attribute directives
なぜ 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.css の heroes クラスは、下記のように変換されます。
.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 のクラス名が異なるため適用されない、と。
なるほどねぇ~。
一旦切ります。
(まぁこういうことしているから終わらないんだよねぇ~。楽しいから良いのだけれども)