はじめに
構成
- 環境構築: https://qiita.com/rayan/items/5d04ee2ca7860c220dec
- ログインページ: https://qiita.com/rayan/items/1f0576395b9727635461
- メニュー: 今回
GitHubリポジトリ
準備中
操作するファイル
- src
- components
- Drawer.js
- Header.js
- router
- index.js
- views
- MainMenu.vue
- components
src/components/Drawer.vue
ナビゲーションメニュー。いくつかのビューで共通する要素のため、componentsの中に入っている。
- Drawer.vue内では
show
というpropを定義しています。これはDrawer要素の表示の有無を示している。 - ナビゲーションメニュー表示後、閉じた場合には
show=false
になる。この変化を親コンポーネントであるHeaderのshow
に適用するために以下の処理を行う。-
show
の変化(true->false, false->true
)をwatch
で検出。 -
this.$emit('update:show', this.show)
を行う。- これは(
true->false, false->true
)の両方で発火するため、this.$emit('update:show', false)
にするとDrawerが開かなくなる。
- これは(
- 親であるHeaderに
:show.sync="show"
がある。これは以下の二つの役割を担っている。-
:show="show"
ではpropであるshow
(左)にshow
(右)の値を代入 -
v-on:update:show="show = $event"
では子のupdate:show
イベントを受けて親のshow
(右)の値を更新
-
-
<template>
<v-navigation-drawer
v-model="show"
absolute
temporary
>
<v-list>
<v-list-item-group
v-model="selectedItem"
color="primary"
>
<v-list-item
v-for="(item, i) in items"
:key="i"
:to="item.link"
>
<v-list-item-icon>
<v-icon v-text="item.icon"></v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title v-text="item.text"></v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-navigation-drawer>
</template>
<script>
export default {
name: "Drawer",
components: {
//
},
props: {
show: {
type: Boolean,
default: false
}
},
data: () => ({
selectedItem: 1,
items: [
{ text: 'Preferences', icon: 'mdi-account-cog', link: '/userPreferences'},
{ text: 'Item Registeration', icon: 'mdi-tag-plus' , link: '/itemRegisteration'},
{ text: 'Item List', icon: 'mdi-tag-multiple', link: '/itemList'},
]
}),
watch: {
show() {
this.$emit('update:show', this.show);
}
},
};
</script>
src/components/Header.vue
ヘッダー要素。いくつかのビューで共通する要素のため、componentsの中に入っている。
-
v-app-bar-nav-icon
をクリックすることによって、propsを用いてインポートしたDrawerを表示している。- 表示していない状態(
show=false
)から表示する状態(show=true
)に変化させる。
- 表示していない状態(
- Header.vue内では
title
というpropを定義している。これはHeader要素で表示する文字列を示している。
<template>
<div>
<v-card
class="mx-auto"
tile
>
<v-toolbar>
<v-app-bar-nav-icon @click.stop="show = !show"></v-app-bar-nav-icon>
<v-toolbar-title>{{title}}</v-toolbar-title>
</v-toolbar>
</v-card>
<Drawer :show="show" v-on:update:show="show = $event"/>
</div>
</template>
<script>
import Drawer from '@/components/Drawer'
export default {
name: "Header",
components: {
Drawer
},
data: () => ({
show: false
}),
props: {
title: String,
},
};
</script>
src/views/MainMenu.vue
メインメニューの要素。
- props
-
<Header :title="title"/>
によってHeaderのpropであるtitle
(左)の値をtitle
(右)の値に設定する。
-
<template>
<div>
<Header :title="title"/>
</div>
</template>
<script>
import Header from '@/components/Header'
export default {
name: "MainMenu",
components: {
Header
},
data: () => ({
title: 'Main Menu'
}),
};
</script>
router/index.js
新しくつくったMainMenuページの情報を追加する。
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
const routes = [
{
path: "*",
redirect: "/"
},
{
path: "/mainMenu",
name: "MainMenu",
meta: { requiresAuth: true },
component: () =>
import("@/views/MainMenu.vue"),
},
{
path: "/",
name: "Authentication",
component: () =>
import("@/views/Authentication.vue"),
},
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes,
});
router.beforeEach((to, from, next) => {
let requiresAuth = to.matched.some(record => record.meta.requiresAuth)
let currentUser = firebase.auth().currentUser
if (requiresAuth) { // if this page requires auth, redirect to auth page
if (!currentUser) {
next({
path: '/',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // this is required
}
})
export default router;
Build
- ビルドし、動作をテストする。動作のテストにはFirebase Emulatorが必要であるため、起動する。
npm run build
firebase emulators:start
次回
ユーザー設定確認・変更ページ