问题
主要讲问题解决方案,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>
刷新页面状态(数据)会清空
解决方案一:WebStorage
手动存储在localStorage或sessionStorage中
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)
}
},
})
刷新页面状态(数据)还在
解决方案二:插件
实际开发中状态(数据)肯定是比较多的,全都自己手动存储在localStorage或sessionStorage中工作量比较大,可以借助一些插件来实现
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 })],
})
刷新页面状态(数据)还在,其他更多功能自行查询手册
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持久化插件,当然实际封装不会这么简单,这里只是写个简单的示例介绍下原理