どうも、趣味でVue.jsを触っているVue.js初心者のこじらです。
今回は、
「ログイン情報をローカルストレージで保存させて、ブラウザのリロードがされた場合も情報を保持できるようにしたいな🤔」
と思って、Vue.jsにおけるローカルストレージの使い方について調べたときの備忘録です。
出回っている記事だとなんか難しくてよく分からなかったことが、この記事を書く動機になりました。
初心者の同志が参考にしてくれると嬉しい。
やろうとしたこと
実装環境
- vue-cli
- 認証サーバを使用したログイン実装済み(Twitter API、firebaseを使用)
- Vuex実装済み
- Nuxt.jsなし
まぁ環境はこんな感じです。
やりたいこと
ブラウザをリロードすると、一回画面遷移をしないとfirebaseから受け取った情報がstore(vuex)の方に反映されない、それを何とかするのが今回の目的です。
そして、懸念点はローカルストレージの監視がうまくできるかでした。
ナビゲーションバーは、ユーザがサイトを開いたときに一度だけマウントされる仕組みにしています。
そのため、ナビゲーションバーに配置していた「アカウント管理」ボタンと「ログイン」ボタンのログイン状態による制御は、ログイン状態を監視する方法により実装する必要があります。
これまでは、firebaseがログイン情報をある程度管理してくれていた(?)ので、以下のようにstoreを監視するだけでなんかうまくいってました。
Navbar.vue(独自で実装したナビゲーションバー)
mounted() { this.$store.watch( (state, getters) => getters.userId, (newValue) => { this.isLogin = newValue; } ); },
この辺がローカルストレージを使用するようにした場合、どういう挙動になるのかイメージできていなかったという感じです。
vuex-persistedstateとは?
結論から言うと、vuex-persistedstateをインストールして使ったら簡単に実装できました。
vuex-persistedstateを使うメリット
- vuex-persistedstateを使うメリットってあるん?
- localStorage.getItem()みたいにローカルストレージ素使いじゃダメなん?
- なんかvuex-persistedstateを使ったときのローカルストレージの値の取得方法がググっても出てこないけどなんでなん?
というのが調べている上での主な疑問でした。
色々試しているうちに納得がいく答えが見つかりました。
vuex-persistedstateは、「(Vuexの)State情報とローカルストレージの状態をなんかいい感じに同期をとってくれるもの」です。
そのため、ただローカルストレージに値を突っ込んだり、取得したりする分にはlocalStrage.getItem()のように素でやっちゃえばいいんですが、それだとVueのwatchを使用した監視などの高度なことができないんですよね。
(やり方はあるんだろうが、難しい又は冗長になるという意味。)
実装
どうせソースが見たいんだろということで一部切り抜いて公開
store/index.js
import Vue from 'vue' import Vuex from 'vuex' import createPersistedstate from 'vuex-persistedstate' Vue.use(Vuex) export default new Vuex.Store({ strict: true, state: { // firebaseを使用して引っこ抜いたTwitterのuser_id userId: "", }, getters: { userId(state) { return state.userId; } }, mutations: { setUserId(state, userId) { state.userId = userId; }, }, actions: { setUserId({ commit }, value) { commit('setUserId', value); } }, modules: { }, plugins: [createPersistedstate({ key: '任意のキー' })], })
任意のキーのところは他のサイトとは被らない値を使った方が良いらしいです。
今回はブラウザ内で情報を共有してほしかったのでローカルストレージを使用しましたが、セッションストレージの方が用途は多そうな気がします。
main.js
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' import vuetify from './plugins/vuetify' import firebase from 'firebase/app' import 'firebase/auth' import titleMixin from '@/title'; import sanitizeHTML from 'sanitize-html'; Vue.prototype.$sanitize = sanitizeHTML; Vue.mixin(titleMixin); Vue.config.productionTip = false const firebaseConfig = { // ひみつ }; // Twitter APIからのアカウント情報を監視している部分 firebase.initializeApp(firebaseConfig); const app = () => { firebase.auth().onAuthStateChanged(currentUser => { if (currentUser) { // ログインしている場合 store.dispatch("setUserId", currentUser.providerData[0].uid); } else { // ログインしていない場合 store.dispatch("setUserId", null); } }), new Vue({ router, store, vuetify, render: h => h(App), }).$mount('#app') } app();
this.$store.dispatch()でvuexを操作すれば、ローカルストレージの方にも反映してくれます。
ナビゲーションバーのmounted部分の実装
mounted() { this.isLogin = !!this.$store.getters.userId; this.$store.watch( (state, getters) => getters.userId, (newValue) => { this.isLogin = newValue; } ); },
isLoginが
- falseの場合は「ログイン」ボタン
- trueの場合は「アカウント管理」ボタン
を表示させるといった風味。
マウント時はローカルストレージのユーザIDを取得して、その後ログイン情報に変更が加えられたらwatchが発動しボタンを制御してくれます。
Chromeデベロッパーツールでチェック
ログイン時
ちゃんと入ってますねー
非ログイン時
ちゃんと消えてますねー
おわり
一通り動作検証をした結果すべて理想の挙動になっていたので、この辺の実装はいったん完了ということにしました。
まぁ、vuex-persistedstateが何やってるのか詳しくは理解してませんが、うまいことVuexとローカルストレージの同期をとってくれてるんだろうなとw
(受け取ったfirebaseの情報を使えばローカルストレージを使わなくても実装できたんじゃ…?まぁいいやw)
こじらでした
じゃ
コメント