【Vue + Vuetify】v-navigation-drawer を固定表示のままリンク遷移させる方法


はじめに

皆さんおはこんばにちは。
エンジニア歴1年目、現場未経験の弱小自称 Web エンジニアです。

今回は、Twitter PC版のように
サイドナビゲーションバーを表示させたまま画面遷移させるべく
試行錯誤した経緯を記録しようと思い、本記事の作成にいたった次第でございます。

やりたいこと

  • リンクをクリックしてページの切り替えをしても、常に左側のドロワーが表示されるようにする

先に結論から述べておくと
ルートの設定を入れ子構造にすれば無事に解決しました。

最初のコード(失敗例)

特に何の考えもなく実装しようとした最初のコードを以下に記載します。

App.vue
<template>
  <v-app>
    <v-main>
      <router-view />
    </v-main>
  </v-app>
</template>

<script>

export default {
  name: 'App',
};
</script>


Main.vue
<template>
    <div>
        <SideNav />
            <v-content>
                <v-container fluid fill-height align-start justify-center>
                    <router-view />
                </v-container>
            </v-content>
    </div>
</template>

<script>
import SideNav from '../components/SideNav.vue'

export default {
    components: {
        SideNav,
    }
}
</script>


SideNav.vue
<template>
    <v-navigation-drawer permanent absolute>
        <v-list dense nav>
            <v-list-item
                v-for="item in items"
                :key="item.title"
                :to="item.link"
            >
                <v-list-item-icon>
                    <v-icon>{{ item.icon }}</v-icon>
                </v-list-item-icon>

                <v-list-item-content>
                    <v-list-item-title>{{ item.title }}</v-list-item-title>
                </v-list-item-content>
            </v-list-item>
        </v-list>
    </v-navigation-drawer>
</template>

<script>
export default {
    data() {
        return {
            items: [
                {title: 'ホーム', icon: 'mdi-home', link: {name: 'home'}},
                {title: '通知', icon: 'mdi-bell', link: {name: 'notification'}},
                {title: 'メール', icon: 'mdi-email', link: {name: 'email'}},
            ]
        }
    }
}
</script>


router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'

import Main from '../views/Main.vue'
import Home from '../components/Home.vue'
import Notification from '../components/Notification.vue'
import Email from '../components/Email.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'main',
    component: Main,
  },
  {
    path: '/home',
    name: 'home',
    component: Home,
  },
  {
    path: '/notification',
    name: 'notification',
    component: Notification,
  },
  {
    path: '/email',
    name: 'email',
    component: Email,
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router


↑GIF画像の通りリンクをクリックした瞬間、ドロワーが消えてしまう!!

リンク先に遷移自体は出来ているようなのに何故……

試行錯誤の経緯

自分が思い描くドロワーを実装させる為にはどうすれば良いのだろうか。
拙者が無い頭をひねって導き出した対処法は以下の3つ。

v-navigation-drawer に何かそういうプロパティ無いの??
→ ドキュメントなどを読み漁ったかぎり、見つかりませんでした。

router-view を App.vue にも Main.vue にも書いているのが不味いの??
→ 名前付きビューってやり方が出て来たけど、何かこれも違いそう。

③ ネスト? そういや Home.vue とかって Main.vue と入れ子構造になってないかな?
→ 予感的中でした!!

ルートの設定をネストにする

「ホーム画面」「通知画面」「メール画面」
それぞれを形作る Home.vue、Notification.vue、Email.vue は
Main.vue に内包されるコンポーネントになります。

そのため、以下のようにルートの設定を入れ子構造にしてあげることで
目標とする状態へと到達することが出来ました。

router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'

import Main from '../views/Main.vue'
import Home from '../components/Home.vue'
import Notification from '../components/Notification.vue'
import Email from '../components/Email.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'main',
    component: Main,
    children: [
      { path: 'home', name:'home', component: Home },
      { path: 'notification', name:'notification', component: Notification },
      { path: 'email', name:'email', component: Email },
    ]
  },
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router

トライアンドエラーあるのみンゴね〜。

参考記事