（６）アプリケーションメニューとRouterでの画面遷移 

Vuetifyのアプリケーションメニュー、上部のバーを追加して、アプリケーションの骨格を作ってみます。さらに、VueのRouter機能を導入することで、シングルページアプリケーション（SPA）の画面遷移を実装してみます。

説明の途中でgitが必要となるので、gitのインストールがまだの場合は、[gitをインストール](https://git-scm.com/downloads)しておいてください。

#参考文献
- [（１）Vue + Vuetify でローカル開発環境をセットアップ](https://qiita.com/kztmy/items/b0d8b824b777b7f839bd)
- [（２）Vue + Vuetify をVisual Studio Codeで実行・デバッグ](https://qiita.com/kztmy/items/84d2e69fb6ebeefa05b2)


#プロジェクトの作成
まず、Routerの機能を追加したプロジェクトを作成します。

```> vue create appbar01```

![vue_project_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/f054d1fb-4888-44e4-86b1-1e1493aec31b.png)

```Manually select features```を選択します。

さらに、```Router```を選択します。他の項目はデフォルトのままとします。

![vue_project_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/0c010620-5428-9f39-b05b-f7855772e237.png)

Vueのバージョンは、2.xを選択し、残りの選択項目も全てデフォルトとします。
次に、Vuetifyをプロジェクトに追加します。

```> cd appbar01```
```> vue add vuetify```

Vuetifyのインストールは、デフォルトのままです。
Visual Studio Codeを起動して、Terminalから、

```> npm run serve```

と入力し、Vueのコンパイルをして、開発用のWebサーバを起動します。ブラウザを起動してVuetifyの画面が表示されることも確認します。（詳細は、こちらを参考にしてください）

![vuetify_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/7392d932-473c-224b-39ca-13c716dd87d5.png)

プロジェクトを作成するときに選択したRouterの実装が、Vuetifyをインストールしたことで上書きされてしまったので、App.vueを元に戻したいと思います。ソースコードがgitで管理されているので、Visual Studio Codeから簡単に元に戻すことができます。

![vc_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/726f19e2-23c3-8f4c-bc1e-88cc84919458.png)

上記のように、Visual Studio Codeのソースコード管理メニューを選択し、赤丸のアイコン（Discard changes）をクリックすると、Vuetifyでインストールされた部分が元に戻ります。

![vuetify_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/8a1b68fb-8796-6261-a8fb-b24d31268372.png)

```src/components/HelloWorld.vue``` はVuetifyの変更が入ったままなので、VueとVuetifyのアイコンが同時に表示されていますが、とりあえず、"Home" と "About"のリンクが上部に表示されたと思います。それぞれは、```/``` ```/about```へリンクされていますが、これらは、VueのRouterの機能が使われています。

#Router

Routerがどのように動いているか見てみます。
Visual Studio Codeから、```src/router/index.js``` を見てください。

```vuejs
...

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]
```

ここで、"/"はHome('../views/Home.vue')を呼び出し、"/about"はAbout('../views/About.vue')を呼び出すように設定されています。
aboutページについては、Routerをインストールした時に入っているコメントにもあるように、/aboutが呼び出された時に初めて画面が読み込まれる遅延ローディング（lazy loading）の仕組みを使うようになっています。こうすることで、"/"が呼ばれた時にはAbout画面が読み込まれないので、ロードが早くなるメリットがあります。（詳細は、[遅延ローディングルート](https://router.vuejs.org/ja/guide/advanced/lazy-loading.html)を参照）

さらに、```Home.vue``` は、コンポーネントとして、```src/components/HelloWorld.vue``` を読み込んでいます。VueとVuetifyのアイコンが表示されているのは、HelloWorld.vueがそのようになっているためです。

#App.vue, v-app-bar

ここで、上部に検索などで使うためのバーと、左側にメニューを追加してみたいと思います。
これらは、VuetifyのUIコンポーネントに用意されている、```<v-app-bar>``` と```<v-navigation-drawer>``` を使うことで、簡単に追加することができます。


App.vueを開いて、```<v-app>``` ```<v-main>```で囲みます。

```vue

<template>
  <v-app>
    <v-main>
      <div id="nav">
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
      </div>
      <router-view />
    </v-main>
  </v-app>
</template>
```
![vc_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/a2f93f19-488b-d835-32d0-f86c7d374d92.png)

```<v-app>``` の下に、```<v-app-bar>```を追加します。
```<v-app>``` ```<v-main>``` ```<v-container>``` ```<v-app-bar>``` ```<v-navigation-drawer>``` をどのように使えば良いかは、Vuetifyの[Application](https://vuetifyjs.com/en/components/application/)ガイドに詳しく説明されています。

```vue
<template>
  <v-app>
    <v-app-bar app color="primary" dark>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>

      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-filter</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-app-bar>

    <v-main>
      <div id="nav">
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
      </div>
      <router-view />
    </v-main>
  </v-app>
</template>
```

これで、上部にメニュー、検索、フィルターなどのアイコンが表示されたバーが追加されました。
```<v-app-bar>``` に指定している```app``` というプロパティは、```<v-main>```の外にあるVuetifyのUIコンポーネントを、自動的に、正しくレイアウトするために必要となります。

![vuetify_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/cb8fb201-910f-530c-9a04-365f8544720a.png)


#v-navigation-drawer

次に、メニューを追加してみようと思います。
メニューは、```<v-navigation-drawer>``` で追加できます。メニューは左上のアイコンをクリックすると左側から表示され、メニューを選択すると、自動的にメニュー自体はクローズするようにします。
また、メニューには、ログインした時のアバター（写真）の表示と、Home, About画面への遷移を付け加えたいと思います。

まずは、メニューを左に表示してみます。

```vue
<template>
  <v-app>
    <v-navigation-drawer permanent app>
      <v-list nav dense>
        <v-list-item-group active-class="deep-purple--text text--accent-4">
          <v-list-item>
            <v-list-item-title>Home</v-list-item-title>
          </v-list-item>

          <v-list-item>
            <v-list-item-title>About</v-list-item-title>
          </v-list-item>

        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>

    <v-app-bar app color="primary" dark>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>

      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-filter</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-app-bar>

    <v-main>
      <div id="nav">
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
      </div>
      <router-view />
    </v-main>
  </v-app>
</template>

```

ここで、下半分の```<v-app-bar>``` と```<v-main>```の部分は、上記と同じです。
```<v-navigation-drawer>``` のpermanentは、常にメニューを表示するためのプロパティです。```<v-app-bar>``` と同様に、appプロパティを指定してレイアウトが正しく行われるようにしています。

![vuetify_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/c9f2aea2-574b-ac22-8eb7-1165e19cc219.png)

#メニューアイコンを使って表示

では、メニューアイコンをクリックするとメニューが表示され、再度クリックするとメニューが非表示になるようにしてみます。さらに、メニューをクリックすると、```/``` と```/about``` にそれぞれリンクが遷移するようにしてみます。
App.vueを以下のように変更します。

```vue
<template>
  <v-app>
    <v-navigation-drawer v-model="drawer" app>
      <v-list nav dense>
        <v-list-item-group active-class="deep-purple--text text--accent-4">
          <v-list-item v-on:click="hideDrawer" to="/">
            <v-list-item-title>Home</v-list-item-title>
          </v-list-item>
          <v-list-item v-on:click="hideDrawer" to="/about">
            <v-list-item-title>About</v-list-item-title>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>

    <v-app-bar app color="primary" dark>
      <v-app-bar-nav-icon v-on:click="drawer = true"></v-app-bar-nav-icon>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-filter</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-app-bar>

    <v-main>
      <div id="nav">
        <router-link to="/">Home</router-link> |
        <router-link to="/about">About</router-link>
      </div>
      <router-view />
    </v-main>
  </v-app>
</template>

<script>
export default {
  data: function () {
    return {
      drawer: false
    };
  },
  methods: {
    hideDrawer: function () {
      this.drawer = false;
    },
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}

#nav {
  padding: 30px;
}

#nav a {
  font-weight: bold;
  color: #2c3e50;
}

#nav a.router-link-exact-active {
  color: #42b983;
}
</style>
```

![vc_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69430/77bb2668-86fb-e007-51ad-782b25109aa4.png)

変更したところは以下のようなところです。

```<v-navigation-drawer>``` に変数drawerを追加して、メニューの表示・非表示をコントロールできるようにしています。```<v-navigation-drawer>``` では、v-modelでバインドされた変数（名前は任意です）がfalse、あるいは、変数そのものが存在しない時は、メニューが表示されず、バインドされた変数がtrueの時には表示されるようになっています。
したがって、クリックするたびに、trueとfalseを切り替えてあげることで、表示・非表示を切り替えることができるわけです。

まず、```<v-app-bar-nav-icon>``` にクリックした時の動作を追加しています。

```
 <v-app-bar-nav-icon
    v-on:click="drawer = true"
></v-app-bar-nav-icon>
```

```<v-list-item>``` には、クリック時に、hideDrawer()が呼び出されるようにして、```<script>``` の部分に、

```
  methods: {
    hideDrawer: function () {
      this.drawer = false;
    },
  }
```
として、変数drawerをfalseに設定するようにしています。これによって、メニューがクリックされると、メニューが閉じるようになっています。

また、メニューのHomeやAboutがクリックされたら、"/" "/about" にページ内で遷移するように、```<v-list-item>``` には、```to=``` を使ってそれぞれのURLにリンクしています。もし、Routerで設定している自分自身のアプリケーション以外の外部のサイトへのリンクをするには、toの代わりに、```href="https://www.google.com```のように指定します。


#まとめ

VueのRouter機能を使って、複数ページに遷移するシングルページアプリケーション（SPA)を作成しました。app-bar, navigation-drawerを使ったアプリケーションのフレームも作成してみました。

#おまけ: Visual Studio Codeのショートカット

覚えてくと便利な、Visual Studio Codeのショートカットを書いておきます。
詳細の一覧は、[Windowsショートカット](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-windows.pdf)と、[Mac用ショートカット](https://code.visualstudio.com/shortcuts/keyboard-shortcuts-macos.pdf)にありますが、私がよく使うものを２つだけ。

- (Mac) Command + Shift + y,  (Windows) Control + Shift + y
    デバッグコンソールの表示・非表示を切り替えできます。
- (Mac) Command + Shift + p,  (Windows) Control + Shift + p
　　上部のコマンドパレットを開きます。Format Documentと入力するとエディターのコードをフォーマットできます。ショートカットをカスタマイズして割当てすればいいのですが。