2020/05/25
[第3回]Nuxt.js+Vuetifyでレイアウトを整える
今回は、Nuxt.js + Vuetifyベースのアプリのレイアウトを整理します。
Nuxt.jsにはlayoutsという機能があります。
共通のheaderやfooterなどはlayoutsのリソースで定義し、各pageからは、layoutの種類を指定することで、headerやfooterなどの記述をキレイにまとめることができるようになっています。
以下のような構成になっています。
gdrive-manager
└── client
├── pages <- ここに各ページを定義して、どのlayoutを指定するかのプロパティを記述できます
└── layouts <- これです
note
前回の続きです。
まだご覧になっていない方は、こちらからご覧ください。
不要なリソースの削除
まずは、初回に作成したアプリから不要なデータを削除しましょう。
VuetifyをDesign Frameworkとして採用していると、
VuetifyのLogoデータなどが自動で作成されているので、そちらを削除します。
以下のように編集しましょう
-
以下のファイルを削除します。
- client/components/Logo.vue
- client/components/VuetifyLogo.vue
- client/pages/inspire.vue
- client/static/icon.png
- client/static/v.png
- client/static/vuetify-logo.svg
-
faviconを更新します
- client/static/favicon.ico
- こちらのファイルを使って上書きしてください
- client/static/favicon.ico
-
defaultのlayoutファイルを編集します。
- client/layouts/default.vue
以下のように編集してください。
<template>
<v-app dark>
<v-app-bar
color="primary"
:clipped-left="$vuetify.breakpoint.lgAndUp"
clipped-right
app
>
<v-toolbar-title
style="width: 300px"
class="ml-0 pl-4"
@click="$router.push('/')"
>
<span class="hidden-sm-and-down">{{ title }}</span>
</v-toolbar-title>
</v-app-bar>
<v-content>
<v-container>
<nuxt />
</v-container>
</v-content>
</v-app>
</template>
<script>
export default {
data() {
return {
title: 'GDrive Manager'
}
}
}
</script>
- topページを編集します。
- client/pages/index.vue
以下のように編集してください。
<template>
<v-row justify="center">
<v-col cols="12" md="8">
<p class="display-1">{{ title }}</p>
</v-col>
</v-row>
</template>
<script>
export default {
data() {
return {
title: '[第3回]Nuxt.js+Vuetifyでレイアウトを整える'
}
}
}
</script>
ここで、いったん起動してみて、表示を確認してみましょう。
ターミナルで以下を実行してみてください。
% yarn run dev
http://localhost:3000/にアクセスして、以下のように表示されていればOKです。
Vuetifyについて
VuetifyはMaterial DesingをベースとしたVue.js用のフレームワークとなっています。
例えば、Buttonsをご覧いただきたいのですが
<v-btn color="primary">Primary Button</v-btn>
とマークアップするだけで、Material Designベースのボタンを表示することができます。
Buttonだけではなく、様々なUI部品が揃っていてとても便利です。
Vuetifyで開発するときはUIコンポーネントで定義されているものをよく読んで、利用するようにしましょう。
今回はアプリのレイアウトを整えるのがテーマですので、アプリケーションレイアウト — Vuetify.jsというページがとても参考になります。UIコンポーネントだけでなく、こちらのページもよく読んでおくと良いでしょう。
レイアウトを編集しよう
今回の本題です。実際にレイアウトファイルを整備していきましょう。
VuetifyのThemeを編集しよう
client/assets/variables.scss
以下の行を追加します。
$active-color: #6B38FB;
client/assets/overrides.sass
以下の内容でファイルを作成します。
こちらは、VuetifyのCSSをカスタマイズ(上書き)するためのファイルです。
.v-application
.primary--text
color: #6B38FB !important
caret-color: #6B38FB !important
a
cursor: pointer
color: rgba(0, 0, 0, 0.87)
background-color: transparent
.v-list-item--active
color: $active-color!important
client/nuxt.config.js
先ほど作った、overrides.sassを読み込むようにします。
/*
** Global CSS
*/
css: [{ src: '~/assets/overrides.sass', lang: 'sass' }],
さらに、vuetify moduleの設定箇所を以下のように修正します。
lightテーマを使用して、primaryとsecondaryの色を指定しています。
こう記述しておくことで、後々 color=“primary” や color=“secondary” などと記述することができて便利です。
/*
** vuetify module configuration
** https://github.com/nuxt-community/vuetify-module
*/
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: false,
themes: {
light: {
primary: '#FFFFFF',
secondary: '#6B38FB'
},
dark: {
primary: '#FFFFFF',
secondary: '#6B38FB'
}
}
}
},
client/layouts/default.vue
- app barのタイトルの横にハンバーガーメニューを表示させましょう
<v-app-bar
color="primary"
:clipped-left="$vuetify.breakpoint.lgAndUp"
clipped-right
app
>
<v-app-bar-nav-icon @click.stop="toggleDrawer" /> <- この行を追加
<v-toolbar-title
style="width: 300px"
class="ml-0 pl-4"
@click="$router.push('/')"
>
- ユーザーアバターとログアウトボタンを表示させましょう
- 以下のコードを
の閉じタグの後に追加しましょう
- 以下のコードを
<v-spacer />
<v-menu
offset-y
transition="scroll-y-transition"
:close-on-click="true"
:close-on-content-click="true"
>
<template v-slot:activator="{ on }">
<v-btn icon large class="mr-1" v-on="on">
<v-avatar size="38px" item>
<v-icon dark x-large>mdi-account-circle</v-icon>
</v-avatar>
</v-btn>
</template>
<v-list dense>
<v-list-item
v-for="(item, index) in avatarMenuItems"
:key="index"
@click="avatarMenuItemClick(item.href)"
>
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ item.text }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
- navigation drawerを表示させましょう
- 以下のコードを
の閉じタグの後に追加しましょう
- 以下のコードを
<v-navigation-drawer
v-model="drawer"
:clipped="$vuetify.breakpoint.lgAndUp"
app
>
</v-navigation-drawer>
- footerを表示させましょう
- 以下のコードを
の閉じタグの後に追加しましょう
- 以下のコードを
<v-footer app>
<span>© {{ new Date().getFullYear() }} {{ author }}</span>
</v-footer>
- scriptを修正しましょう
- dataに drawer / avatarMenuItems / authorプロパティを追加します
- avatarをクリックすると出てくるメニューは今後追加する可能性も考慮して、配列で定義してあります。
- methodsプロパティを追加して、toggleDrawer / avatarMenuItemClick関数を定義しましょう
- dataに drawer / avatarMenuItems / authorプロパティを追加します
<script>
export default {
data() {
return {
drawer: null,
title: 'GDrive Manager',
avatarMenuItems: [
{ icon: 'mdi-logout', text: 'Logout', href: '/logout' }
],
author: 'Kumanote,LLC.'
}
},
methods: {
toggleDrawer() {
this.drawer = !this.drawer
},
avatarMenuItemClick(href) {
switch (href) {
case '/logout':
window.alert('TODO implement logout')
break
default:
this.$router.push(href)
break
}
}
}
}
</script>
全体としては以下のようになります。
<template>
<v-app dark>
<v-app-bar
color="primary"
:clipped-left="$vuetify.breakpoint.lgAndUp"
clipped-right
app
>
<v-app-bar-nav-icon @click.stop="toggleDrawer" />
<v-toolbar-title
style="width: 300px"
class="ml-0 pl-4"
@click="$router.push('/')"
>
<span class="hidden-sm-and-down">{{ title }}</span>
</v-toolbar-title>
<v-spacer />
<v-menu
offset-y
transition="scroll-y-transition"
:close-on-click="true"
:close-on-content-click="true"
>
<template v-slot:activator="{ on }">
<v-btn icon large class="mr-1" v-on="on">
<v-avatar size="38px" item>
<v-icon dark x-large>mdi-account-circle</v-icon>
</v-avatar>
</v-btn>
</template>
<v-list dense>
<v-list-item
v-for="(item, index) in avatarMenuItems"
:key="index"
@click="avatarMenuItemClick(item.href)"
>
<v-list-item-action>
<v-icon>{{ item.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ item.text }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
<v-navigation-drawer
v-model="drawer"
:clipped="$vuetify.breakpoint.lgAndUp"
app
>
</v-navigation-drawer>
<v-content>
<v-container>
<nuxt />
</v-container>
</v-content>
<v-footer app>
<span>© {{ new Date().getFullYear() }} {{ author }}</span>
</v-footer>
</v-app>
</template>
<script>
export default {
data() {
return {
drawer: null,
title: 'GDrive Manager',
avatarMenuItems: [
{ icon: 'mdi-logout', text: 'Logout', href: '/logout' }
],
author: 'Kumanote,LLC.'
}
},
methods: {
toggleDrawer() {
this.drawer = !this.drawer
},
avatarMenuItemClick(href) {
switch (href) {
case '/logout':
window.alert('TODO implement logout')
break
default:
this.$router.push(href)
break
}
}
}
}
</script>
最後に、ローカルサーバー起動してみて、表示を確認してみましょう。
ターミナルで以下を実行してみてください。
% yarn run dev
http://localhost:3000/にアクセスして、以下のように表示されていればOKです。
global side navigation、global header, global footerなどを組み込むことができました。
今回はこれで以上になります。
今回作成したファイルは GithubのPull Request からもご覧いただけます。
次回は、ログイン用の画面のレイアウトを作成して、ログイン画面を作っていこうと思います。