Angularでの基本的なページレイアウトを理解する

前回ではAngularのプロジェクトを構成する、”コンポーネント”、”モジュール”につて解説していきました。
[Angularプロジェクトの構成](https://qiita.com/KaoruIto76/items/7b4bd6b0fd4bb952df2f)

今回はそれらを使って基本的なページのレイアウトを組んでいきたいと思います！

それではいきましょうーー！

## Headerの実装

前回作ったheaderコンポーネント（鬼誤字ってました恥ずかしい。。。）を以下のように修正して実際にヘッダーを作っていきましょう！
<img width="541" alt="スクリーンショット 2019-06-09 23.30.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/5f159788-4635-6ab0-ddb9-667703fb6853.png">

少しみづらいかもしれませんが、上から
`src/app/header/header.component.ts`
`src/app/app.component.html`
`src/app/header/header.component.html`

になります！

<img width="902" alt="スクリーンショット 2019-06-09 23.32.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/b61603d8-a055-b7fc-9151-fe9c8635ca5f.png">
こんな感じで表示されるはずです！

それではヘッダーを作っていきましょう！
自分で作ってもいいですし、コピペしてくれても構いません！

```html:header.component.html
<header>
  <div class="header-content">
    <div class="logo">
      <a>ロゴだよー</a>
    </div>
    <nav class="navbar">
      <ul>
        <a href=""><li>menu1</li></a>
        <a href=""><li>menu2</li></a>
        <a href=""><li>menu3</li></a>
      </ul>
    </nav>
  </div>
</header>
```

```scss:header.component.scss
header {
  width:                   100%;
  height:                  50px;
  background-color:        #2f3033; 

  .header-content {
    width:                 960px;
    height:                100%;
    margin:                auto;
    position:              relative;

    .logo {
      position:            absolute;
      top:                 50%;
      left:                0;
      transform:           translate(0,-50%);
      font-weight:         bold;
      color:               white;
      font-size:           20px;
    }

    nav {
      position:            absolute;
      top:                 50%;
      right:               0;
      transform:           translate(0%,-50%);

      ul {
        list-style:        none;
        margin:            0;

        li {
          display:         inline-block;
          color:           white;
          padding:         10px;
        }

        li:hover {
          background-color: grey;
          color:            black;
        }
        
        a {
          margin-left:      30px;
        }
      }
    }
  }
}
```

強引感強くてすいません。。。笑
でもこれでこんな感じのヘッダーができたはず！
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/85b9b169-29fb-d7c9-47f2-588c2e2d40ef.gif)

## Footerの実装
お次はフッター！
以前ヘッダーを作ったように、フッターも作っていきましょう！

```console
$ ng g c footer   // ← g(generate),c(component)と略せる
CREATE src/app/footer/footer.component.scss (0 bytes)
CREATE src/app/footer/footer.component.html (25 bytes)
CREATE src/app/footer/footer.component.spec.ts (628 bytes)
CREATE src/app/footer/footer.component.ts (270 bytes)
UPDATE src/app/app.module.ts (557 bytes)
```
適当に、、、、、

```html
<footer>
  <div class="footer-content">
    <ul>
      <a href=""><li>footer rink1</li></a>
      <a href=""><li>footer rink2</li></a>
      <a href=""><li>footer rink3</li></a>
      <a href=""><li>footer rink4</li></a>
    </ul>
  </div>
</footer>
```
```scss

a {text-decoration: none;}

footer {
  width:                  100%;
  height:                 170px;
  margin-top:             30px;
  background-color:       #2f3033;
  position:               relative;
  
  .footer-content {
    display:              flex;
    width:                200px;
    height:               100%;
    margin:               auto;

    ul {
      list-style:         none;
      color:              white;

      li {
        padding:          5px;
        color:            white;
        list-style:       none;
      }
   
      li:hover {
        background-color: grey;
        color:            black;
      }
    }
  }
}

```
headerを追加した時のように`app.cmponent.html`にfooterを追加すれば表示されます

```html

<app-header></app-header>

<router-outlet></router-outlet>

<app-footer></app-footer>
```
とりあえずヘッダーとフッターぽいのができましたね！
<img width="1440" alt="スクリーンショット 2019-06-16 19.07.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/544ac4a5-f223-9eed-4671-2612df1f63c3.png">
**いや前から気になってたけど`<router-outlet>`って誰？**
ってなる人もいると思います
でもその前に各viewがどのように表示されていくのか、全体の構造を一旦整理した方がいいので一旦プロジェクトの`src/index.html`を見てみましょう、こいつが一番親のviewにあたります

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>ExampleAngular</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <app-root></app-root>
</body>
</html>
```
すごくシンプルなHTMLなんですが、`<app-root>`のタグがありますね
今までの作業から、こいつが`app-root`を定義しているコンポーネントの中を参照していることがわかります

一個下の階層にある`app.component.ts`がそれを定義していて、`app-root`のviewに当たる`app.component.html`には先ほど追記した`app-header`や`app-footer`、得体の知れない`router-outlet`がいると思います。

こんな風に大枠のコンポーネントの中に細々としたコンポーネントを作って一つのページができていることがわかりますね！

#####うんそれはわかったけどめっちゃでかい１つのページ作る気？このままだと作りたいものすべてが一個のページに詰まっちまいそうだよ

はい。プログラミング未経験の僕もそう思ってました。
<img width="963" alt="スクリーンショット 2019-06-16 20.25.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/3618e0d9-22a0-869b-edda-c5b2cedfedb4.png">
こんな風に各URLに各HTMLがいるもんだと思っていましたが今回は全体では一個だけ。
初めはピンときませんでした。。。

##SPA?

でも色々調べると、どうやら**SPA**とかいうものの概念を理解しないとダメらしいので調べてみた。
[SPA(Single Page Application)ってなに？
](https://digitalidentity.co.jp/blog/creative/about-single-page-application.html)

一部抜粋

>SPAとは単一のWebページでアプリケーションを構成する設計構造の名称です。

>単一のWebページでコンテンツ切り替えを行うことで、ページ遷移の必要がなく、ブラウザの挙動に縛られないWeb表現を可能にするのです。

むむ、単一のWebページ？なんかすごそう
一応デメリットもありまして

>初期ローディングに時間がかかる
> 実装コストが大幅に増える

らしい。

Angularも**SPA**を作るためのフレームワークらしく、ページ自体は単一で、中のコンテンツ(コンポーネント)を切り替えることで、ページ転移を擬似的に行うことができる。すごい。("普通SPAの理解が先だろ"とは言わないでください。わかっております)

はい。これでSPAとページ全体の構造が理解できましたね〜！

**で、おおもとに帰ります。**

↑らのことから空気を読むと`router-outlet`が表示を切り替えてくれる役割なんだなーってのが予想できます
## routingについて

さっきも言いましたが、SPAでのroutingはページの転移ではなく、表示されているコンテンツ(コンポーネント)の切り替えなので、サーバーを経由しません。(要するに画面転移時にロード画面にならずにすぐ表示される（厳密にいうと違う）。その分初めにロードするから初期ロードが長いよねーって話)

実際にどうやって設定していくかといいますと、実はこの記事を読みながら`angular cli`でプロジェクトを作った人はすでに設定が終わっています。

[Angularプロジェクトの作成](https://qiita.com/KaoruIto76/items/272c7724aa8bbc45d591)
<img width="934" alt="スクリーンショット 2019-06-16 21.53.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/dd931513-660c-002e-fca4-09b72a9699bd.png">
この上から3行目のところを**yes**にすると`src/app/app-routing.module.ts`が作られて、`src/app/app.module.ts`のimportの部分に`AppRoutingModule`が自動で追加されます
作ってない人は以下のコマンドで作ってください

```console
$ng generate module app-routing --flat --module=app
```

じゃぁ新しいコンポーネントを複数作ってroutingも実装してみましょう！

```console
$ ng g c top                // トップページ
.....
...
..
$ ng g c sign-in            // ログインページ
....
...
..
$ ng g c sign-up            // 会員登録ページ
....
...
..
```
↑`top`,`sign-in`,`sign-up`の３つのコンポーネントを作ってみましょう！(あとで使います)
`angular/cli`を使ってcomponentをgenerateするときは`src/app`以上の階層でやると`app/`配下に作られるようになっていて、階層を指定したければ、そのディレクトリ直下で作成すれば大丈夫です！

各コンポーネントのhtmlにはデフォルトで

```html
<p>
  （file名） works!
</p>
```
のように作られるので今は特に編集しなくても切り替わった時に違いがわかるでしょう.

実際にroutingのファイルに設定を追記していきます

```typescript:src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import {SignUpComponent} from 'src/app/sign-up/sign-up.component';
import {TopComponent} from 'src/app/top/top.component';
import {SignInComponent} from 'src/app/sign-in/sign-in.component';

const routes: Routes = [
    { path: 'top',        component: TopComponent    },
    { path: 'signup',     component: SignUpComponent },
    { path: 'signin',     component: SignInComponent },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
```
内容はわかりやすいですね！
`/top`にアクセスしたら`TopComponent`。他も同様です

実際にアクセスしてみましょう！
http://localhost:4200/top
トップページ
<img width="1440" alt="スクリーンショット 2019-06-16 22.23.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/e216cc94-0de2-75a1-36b8-2c03159cda30.png">

http://localhost:4200/signup
会員登録ページ
<img width="1440" alt="スクリーンショット 2019-06-16 22.24.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/ebffbdab-ee46-33c2-42a3-c3dd96c4c707.png">

http://localhost:4200/signin
ログインページ
<img width="1440" alt="スクリーンショット 2019-06-16 22.24.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/af8ccc79-7851-9770-6d58-5c1054217418.png">


####wa---i !!

もうわかっているとは思いますが、ヘッダーや、フッターのような全ページに共通するパーツは`app.component.html`に直接書いておけばこんな風にずっとくっついてきます。
図で書くと⬇︎みたいな感じですね！
<img width="811" alt="スクリーンショット 2019-06-16 19.54.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238826/ffd82ac1-ac96-85c8-cc9b-1d043764cea0.png">

これでテンプレート(html)とスタイル(css)を各コンポーネントに実装してrouting実装するだけで簡単なホームページくらいは作れそうですね！

次回はangular独自のhtmlタグについて書いていきます！

今回の記事に関連したリンク
https://qiita.com/daikiojm/items/46f6b2b355f9f73536e1
https://www.isoroot.jp/blog/1285/
https://digitalidentity.co.jp/blog/creative/about-single-page-application.html