Laravel 8でInertia+Vuetifyにvue-cookiesを… - Laravel JetStream - お試し
はじめに
経緯
Laravel 8でInertia+Vuetifyでテンプレート対応の続きとして、Inertia + Vue + Vuetify でレイアウト構成を組んでみた勢いで vue-cookies を試すことにしたというお話です。
Inertia + Vueでクライアント側の状態管理をするのに、Vuexは使わずに、vue-cookiesを使ってみます。
実現内容
前回作成したレイアウト構成に少し手を加えます。
http://localhost/app02/data-tables
のメニューは<v-navigation-drawers>
を利用し、マウスオーバーするまで折りたたみ状態で表示されるexpand-on-hover
をオンにしていました。
この折り畳み状態の切り替えをマウスオーバーではなくクリックで行い、そしてその状態を画面遷移後も維持するようにする、ということをCookieを利用して実現したいと考えました。
VueでCookieを簡単に扱えるようにするため、vue-cookiesを利用します。
CookieなしのUI変更
せっかくなので、まずは実現する内容についてUIのみ変更し、状態管理をしないとどのような挙動になるのか見てみましょう。
※編集の都度ビルドが必要です。予めnpm run watch
を実行するなどお忘れなく。
1. メニュー(Drawer)の修正
メニューの開閉状態を格納するプロパティをdata () {}
あたりに追加します。(後で消しますが)
drawer: true,
↓
drawer: true,
miniDrawer: true,
<v-navigation-drawer>
のexpand-on-hover
を以下のように変更します。
expand-on-hover
↓
:mini-variant="miniDrawer"
メニューの開閉用のUIを設置するため先頭の<v-list-item>
あたりを書き換えます。
<v-list-item class="px-3">
<v-list-item-avatar size="32" color="grey"></v-list-item-avatar>
<v-list-item-title class="title">メニュー</v-list-item-title>
</v-list-item>
↓
<v-list-item class="px-3">
<v-list-item-avatar size="32" color="grey"
class="cursor-pointer" @click="miniDrawer = !miniDrawer">
</v-list-item-avatar>
<v-list-item-title class="title">メニュー</v-list-item-title>
<v-spacer/>
<v-btn icon @click="miniDrawer = true">
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</v-list-item>
UI関連の変更はこれくらいです。
2. 動作確認
http://localhost/app02/data-tables
にアクセスして動作確認します。
expand-on-hover
を削除したので、折りたたまれたメニューをマウスオーバーしてもメニューが開かなくなりました。
代わりに、:mini-variant="miniDrawer"
あたりの変更により、メニューの左上の<v-list-item-avatar>
をクリックすると、メニューが開閉します。
そして、メニューを開いた状態にしてWelcomeをクリックし、画面遷移してみます。
すると、画面遷移後のメニューは閉じた状態になります。
画面遷移した際に、画面の状態も初期化されるため、メニューが閉じた状態になる、というわけです。
この開閉状態を画面遷移後も維持する仕組みを、vue-cookiesで組んでみようと、そんな話です。
vue-cookiesの導入
まずは、vue-cookiesを導入します。
vue-cookiesについてはこちらを参照してください。
1. パッケージインストール
vue-cookiesパッケージをインストールします。
laradock@8896705ba0d1:/var/www/example-app02$ npm install vue-cookies
実行イメージ
added 1 package, and audited 844 packages in 3s
94 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
2. プロジェクトに適用
app.js
を編集し、vue-cookiesをプロジェクトに組み込みます。
:
import VueCookies from 'vue-cookies';
:
Vue.use(VueCookies);
:
※必要に応じて、Vue.$cookies.config()
で設定も行います。
導入は以上です。
Cookieを管理するミックスインを作成、組み込み
いくつかの方法で実装してみましたが、今回のケースではミックスインに機能をまとめるのが良さそうだったので、この形にしています。(Cookieに保持する情報が異なれば、別の実装の方が良いかもしれません)
※ミックスインについてはこちらを参照してください。
1. ミックスインファイル作成
というわけでresources/js/mixins
ディレクトリを作成し、そこにcookie-manager.js
というファイル名でミックスインを作成します。名前はお好みで。
ミックスインファイルの内容はこんな感じに仕立てました。
export default {
data: () => ({
cookieManager: {
miniDrawer: null
}
}),
computed: {
miniDrawer: {
get () {
if (this.cookieManager.miniDrawer === null) {
return (this.$cookies.get('mini-drawer') === 'close')
}
return this.cookieManager.miniDrawer
},
set (value) {
this.$set(this.cookieManager, 'miniDrawer', value)
this.$cookies.set('mini-drawer', (value ? 'close' : 'open'), Infinity)
}
}
}
}
2. メニュー(Drawer)に組み込み
作成したミックスインをメニューに組み込みます。
まずcookie-manager.js
をimportします。
<script>
↓
<script>
import cookieManager from '@/mixins/cookie-manager'
data () {}
あたりに追加したminiDrawerを削除します。
miniDrawer: true,
mixins定義を追加して、importしたミックスインを適用します。
export default {
↓
export default {
mixins: [cookieManager],
参考:変更後のDrawer.vue
<template>
<v-navigation-drawer
id="commons-drawer"
v-model="drawer"
:mini-variant="miniDrawer"
permanent
app>
<v-layout column>
<v-list-item class="px-3">
<v-list-item-avatar size="32" color="grey"
class="cursor-pointer" @click="miniDrawer = !miniDrawer">
</v-list-item-avatar>
<v-list-item-title class="title">メニュー</v-list-item-title>
<v-spacer/>
<v-btn icon @click="miniDrawer = true">
<v-icon>mdi-chevron-left</v-icon>
</v-btn>
</v-list-item>
<v-divider/>
<template v-for="(link, index) in links">
<inertia-link :key="index" :href="route(link.name)" as="v-list-item">
<v-list-item-action>
<v-icon>{{ link.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title v-text="link.title" />
</v-list-item-content>
</inertia-link>
</template>
</v-layout>
</v-navigation-drawer>
</template>
<script>
import cookieManager from '@/mixins/cookie-manager'
export default {
mixins: [cookieManager],
data () {
return {
drawer: true,
links: [{
name: 'welcome',
icon: 'mdi-home',
title: 'Welcome'
}, {
name: 'dashboard',
icon: 'mdi-view-dashboard',
title: 'Dashboard'
}, {
name: 'data-tables',
icon: 'mdi-view-list',
title: 'DataTables'
}],
}
}
}
</script>
<style scoped>
</style>
動作確認
再度、http://localhost/app02/data-tables
にアクセスして動作確認します。
メニューを開いた状態にしてWelcomeをクリックし、画面遷移してみます。
今度は、画面遷移後もメニューの状態が維持されます。
画面遷移した際に、メニューの状態をCookieから復元することで、メニューの状態が維持されるというわけです。
まとめ
vue-cookiesを導入して、メニューの状態管理を行ってみました。
vue-cookiesを初めて試してみましたが、インスタンスプロパティ経由でCookieを扱えて、使いやすいパッケージという印象です(そんなものかもしれませんが)。
インスタンスプロパティ経由で扱えはするものの、いたるところにthis.$cookies
が登場するのもどうか、ということでミックスイン化しています。こちらはメニューの状態管理だけでなく他の状態管理も行う想定で組んでみた、というところです。実用はしていないので、もっと検証が必要かもしれません。
今回の記事までで、Vuetify入れて、テンプレート化してみたり、vue-cookiesを試してみたりして、なんとなくInertia + Vueによる実装のイメージはわいてきました。
慣れればSPAとの差をあまり意識せずに実装できる気もします。むしろ、ルート設定を重複管理しなくて済んだり、props経由でデータを渡すことでデータを直感的に扱えるので、メリットの方が大きいのではないかと。
そう考えると、Vuetifyを入れずに、JetStreamの標準コンポーネントで組むのも良いかもしれないとも思います(registerとかconfirm-passwordとか用意されている画面を差し替えるのも大変なので)。
取り急ぎ今回はここまで。
Discussion