vuex 与 localStorage 协同工作 引发的思考
发布于 6 年前 作者 virtoolswebplayer 7146 次浏览 来自 分享

使用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()]
});

插件会自动帮你做如下两件事:

  1. 当vuex状态发生改变时,自动同步保存到 localStorage
  2. 当重新加载页面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打交道就像下面这张图

15303530418717.jpg

职责单一带来的好处就是充分的解耦

  • 设计模式 插件模式

其实整个app应用就是插件的集合, vuex 是 vue 的插件, vuex-persistedstate 又是 vuex的插件。vue 和 vuex 在设计之初就充分的考虑到了以插件的方式进行功能扩展。而它们自身只实现领域范围内的事,不做多余的工作。

插件(Plugin)模式向用户提供了一种扩展程序的接口,用户可以在程序本体之外,按照指定接口编写插件来为程序增加功能。

结论: 合理利用设计模式对于提高程序的扩展性和可维护性至关重要。

推荐阅读:

思考方法与领域模型 vuex 插件

3 回复

大神 vuex感觉用处不是特别大哦,一般localstorage搞定

vue 不用 vuex 就好比 react 不用 redux, 用vuex 管理状态,配合 vue-devtools,调试是非常方便的,也便于观察数据变化

@sunmoon22 简单的页面不用,当处理大量页面和数据时候就需要了

回到顶部