vuex持久化

1,463 阅读3分钟

问题

主要讲问题解决方案,vuex基础自行补习吧

vuex可以实现全局状态管理,即实现所有组件间数据共享,但是刷新页面vuex对象会重新加载,状态(数据)会清空

示例:

store/index.js

 import Vue from 'vue'
 import Vuex from 'vuex'
 ​
 Vue.use(Vuex)
 ​
 export default new Vuex.Store({
   state: {
     num: 0
   },
   mutations: {
     add(state) {
       state.num++
     },
     del(state) {
       state.num = 0
     }
   },
 })

views/Home.vue

 <template>
   <div class="home">
     <h2>num:{{ num }}</h2>
     <button @click="add">add</button>
     <button @click="del">del</button>
   </div>
 </template>
 ​
 <script>
 import { mapState, mapMutations } from "vuex";
 export default {
   computed: {
     ...mapState(["num"]),
   },
   methods: {
     ...mapMutations(["add", "del"]),
   },
 };
 </script>

views/Aboue.vue

 <template>
   <div class="about">
     <h2>num:{{ num }}</h2>
     <button @click="add">add</button>
     <button @click="del">del</button>
   </div>
 </template>
 ​
 <script>
 import { mapState, mapMutations } from "vuex";
 export default {
   computed: {
     ...mapState(["num"]),
   },
   methods: {
     ...mapMutations(["add", "del"]),
   },
 };
 </script>

刷新页面状态(数据)会清空

chrome_4uEOhs406Y.gif

解决方案一:WebStorage

手动存储在localStoragesessionStorage

store/index.js

 import Vue from 'vue'
 import Vuex from 'vuex'
 ​
 Vue.use(Vuex)
 ​
 export default new Vuex.Store({
   state: {
     num: localStorage.getItem('num') || 0
   },
   mutations: {
     add(state) {
       state.num++
       localStorage.setItem('num', state.num)
     },
     del(state) {
       state.num = 0
       localStorage.setItem('num', state.num)
     }
   },
 })

刷新页面状态(数据)还在

chrome_NbIua5YTfi.gif

解决方案二:插件

实际开发中状态(数据)肯定是比较多的,全都自己手动存储在localStoragesessionStorage中工作量比较大,可以借助一些插件来实现

vuex-persistedstate

最知名使用最广的一款vuex持久化插件,后来不知道由于什么原因被作者弃用了,但是依旧阻挡不了它的优秀,npm下载量依旧非常之高

npm: www.npmjs.com/package/vue…

安装:

 npm i vuex-persistedstate

store/index.js

 import Vue from 'vue'
 import Vuex from 'vuex'
 // 引入vuex-persistedstate插件
 import createPersistedState from "vuex-persistedstate";
 ​
 Vue.use(Vuex)
 ​
 export default new Vuex.Store({
   state: {
     num: 0
   },
   mutations: {
     add(state) {
       state.num++
     },
     del(state) {
       state.num = 0
     }
   },
   // 默认存储在localStorage
   plugins: [createPersistedState()],
   // 设置存储在sessionStorage
   // plugins: [createPersistedState({ storage: window.sessionStorage })],
 })

刷新页面状态(数据)还在,其他更多功能自行查询手册

chrome_NfqTMgwJi4.gif

vuex-persist

另一个使用比较多的vuex持久化插件

npm: www.npmjs.com/package/vue…

安装:

 npm i vuex-persist

store/index.js

 import Vue from 'vue'
 import Vuex from 'vuex'
 // 引入vuex-persist插件
 import VuexPersistence from 'vuex-persist'
 ​
 Vue.use(Vuex)
 ​
 export default new Vuex.Store({
   state: {
     num: 0
   },
   mutations: {
     add(state) {
       state.num++
     },
     del(state) {
       state.num = 0
     }
   },
   // 默认存储在localStorage
   plugins: [new VuexPersistence().plugin],
   // 设置存储在sessionStorage
   // plugins: [new VuexPersistence({ storage: window.sessionStorage }).plugin],
 })

效果相同就不截图了

vuex-state-persist

自己写的vuex持久化插件,功能没前两个强大,但可以满足基本需求并且量级轻比较小巧,大家可以尝试着使用支持一下

npm: www.npmjs.com/package/vue…

安装:

 npm i vuex-state-persist

store/index.js

 import Vue from 'vue'
 import Vuex from 'vuex'
 // 引入vuex-state-persist插件
 import createPersist from "vuex-state-persist";
 ​
 Vue.use(Vuex)
 ​
 export default new Vuex.Store({
   state: {
     num: 0
   },
   getters: {
   },
   mutations: {
     add(state) {
       state.num++
     },
     del(state) {
       state.num = 0
     }
   },
   // 默认存储在localStorage
   plugins: [createPersist()],
   // 设置存储在sessionStorage
   // plugins: [createPersist({ storage: 'sessionStorage' })],
 })

效果相同就不截图了

封装原理

持久化插件的核心原理是把store.state对象转为json字符串,保存在WedStorage

Store对象中可以设置plugins属性用来设置插件

plugins中插件是一个函数,会在store初始化后调用,函数内部会设置一个钩子函数store.subscribe在每次调用过mutation中的方法后执行

把函数封装起来,在store/index.js中引入使用

utils/VuexStatePersist.js

 // store初始化后调用
 const myPlugin = store => {
   store.subscribe((mutation, state) => {
     // 每次mutation中的方法被调用后执行, state为store.state
   })
 }
 export default persist;

store/index.js

 ...
 import VuexStatePersist from "@/utils/VuexStatePersist";
 ​
 export default new Vuex.Store({
   ...
   plugins: [VuexStatePersist],
 })

第一步要在钩子函数中把state转为json字符串,存储在WedStorage,这样可以实现每次state值变化WedStorage会同步更新

 const persist = store => {
     store.subscribe((mutation, state) => {
         localStorage.setItem('vuex', JSON.stringify(state));
     })
 }

此时还不能完全实现持久化功能,在初始化的时候还需要在WedStorage中读取一下,如果有曾经保存的值则更新到初始化的store.state

 const persist = store => {
     store._state = JSON.parse(localStorage.getItem('vuex')) || store.state;
     // 在插件中不允许直接修改store.state,使用replaceState方法替换store的根状态
     store.replaceState(store._state);
     store.subscribe((mutation, state) => {
         localStorage.setItem('vuex', JSON.stringify(state));
     })
 }

这样就可以实现一个vuex持久化插件,当然实际封装不会这么简单,这里只是写个简单的示例介绍下原理