使用vue开发稍复杂的项目时,为了方便状态管理我们都会引入vuex帮助我们管理整个应用的状态,所以一般会用类似下面的项目结构
|-vue-project
| |-src
| | |-components
| | |-store
| | |-page
按照这种方式我们就可愉快的进行开发了,有一天你希望页面刷新时当前页面的状态依然可以保持,我们首先想到的就是可以把vuex的状态树放到 localStorage
里。这个时候你会怎么办?google一下 vuex localStorage
看看有什么现有的解决方案,于是我们搜索到了vuex-persistedstate
,嗯,它就是我们今天的主角,让我们围绕vuex-persistedstate
展开讨论,看看有什么值得我们学习的地方。
首先 vuex-persistedstate 用起来非常简单。先看下面的用法
安装
npm install vuex-persistedstate
用法
import createPersistedState from "vuex-persistedstate";
const store = new Vuex.Store({
// ...
plugins: [createPersistedState()]
});
插件会自动帮你做如下两件事:
- 当vuex状态发生改变时,自动同步保存到 localStorage
- 当重新加载页面vuex初始化时,自动将 localStorage 存储的数据作为初始状态加载
现在你又可以愉快的进行开发了,不需要对localStorage进行任何操作。唯一要做的就是由你来决定何时清除 localStorage
// 清除所有
window && window.localStorage.clear();
// 清除指定key
window && window.localStroage.removeItem('vuex')
由此引发的思考
几个关键字:
- 职责单一
- 解耦
- 设计模式
我们只做了很少的事件就达到了我们想要的功能,中间没有修改任何store的代码,比如你可能会在每一个 mutation 里操作localStroage
before
state: {
token: null
},
mutations: {
SET_TOKEN(state, token){
state.token = token
}
}
after
state: {
// 你可能会在这里操作 localStorage 获取 token
token: window && window.localStorage.getItem('token')
},
mutations: {
SET_TOKEN(state, token){
state.token = token
// 你可能会在这里操作 localStorage 存储 token
window && window.setItem('token', token)
}
}
如上代码,目的是达到了,但是非常麻烦,代码严重耦合。而且如果想存储更多的值还得额外的去写更多代码,后期的维护成本增加了。所以上面的解决方案不可取。比较而言vuex-persistedstate
的解决方案更加优雅。
Vuex 的 store 接受 plugins 选项,这个选项暴露出每次 mutation 的钩子。Vuex 插件就是一个函数,它接收 store 作为唯一参数:vuex 插件
vuex-persistedstate
正是利用这个vuex提供的这个特性,统一处理与 localStorage 相关的工作。
...
return function(store) {
// 从localStorage 中取值
const savedState = shvl.get(options, 'getState', getState)(key, storage);
// 如果 savedState 有值,则替换 vuex 的 store
if (typeof savedState === 'object' && savedState !== null) {
store.replaceState(merge(store.state, savedState, {
arrayMerge: options.arrayMerger || function (store, saved) { return saved },
clone: false,
}));
}
// 订阅 mutation 的每一次变化,换需决定是否保存到 localStorage
(options.subscriber || subscriber)(store)(function(mutation, state) {
if ((options.filter || filter)(mutation)) {
(options.setState || setState)(
key,
(options.reducer || reducer)(state, options.paths || []),
storage
);
}
});
};
- 职责单一
vuex , vuex-persistedstate 各伺其职, vuex 负责管理 整个 app 的状态,状态在内存中,它没有再多做什么, vuex-persistedstate 负责把内存中的状态同步到 localStorage, 及 把 localStorage存储的数据加载到vuex store, 从头到尾我们的app除了清理工作,再没有和 localStorage打交道就像下面这张图
职责单一带来的好处就是充分的解耦。
- 设计模式 插件模式
其实整个app应用就是插件的集合, vuex 是 vue 的插件, vuex-persistedstate 又是 vuex的插件。vue 和 vuex 在设计之初就充分的考虑到了以插件的方式进行功能扩展。而它们自身只实现领域范围内的事,不做多余的工作。
插件(Plugin)模式向用户提供了一种扩展程序的接口,用户可以在程序本体之外,按照指定接口编写插件来为程序增加功能。
结论: 合理利用设计模式对于提高程序的扩展性和可维护性至关重要。
推荐阅读:
大神 vuex感觉用处不是特别大哦,一般localstorage搞定
vue 不用 vuex 就好比 react 不用 redux, 用vuex 管理状态,配合 vue-devtools,调试是非常方便的,也便于观察数据变化
@sunmoon22 简单的页面不用,当处理大量页面和数据时候就需要了