手写一个Vuex插件优雅同步store状态与本地缓存数据

前言

下文引用一个简单的用户登录状态信息缓存例子,使用vuex中的modules选项对用户状态信息进行分模块维护的,使用plugins插件选项,注册一个用来同步state中的用户状态和本地缓存数据同步更新

了解vuex的modules和plugins选项

modules:用来解决当项目比较复杂时,单一的状态树所导致store对象变得臃肿所导致的维护困难问题,每个模块都可以拥有自己的statemutationactiongetter选项。
plugins:这个选项暴露出每次mutation的钩子。Vuex插件就是一个函数,它接收store作为唯一参数,可在该方法中监听mutation钩子的执行。

新建用户模块

store/modules/user.js

js 复制代码
import { login, logout } from '@/api/user'

const user = {
  state: () => ({
    name: '',
    avatar: '',
    token: null
  }),
  mutations: {
    setUser(state, data = {}) {
      console.log('setUser', data)
      const { name, avatar, token } = data
      state.name = name
      state.avatar = avatar
      state.token = token
    },
    removeUser(state) {
      state.name = ''
      state.avatar = ''
      state.token = null
      console.log('removeUser')
    }
  },
  actions: {
    login({commit}, data = {}) {
      const { username, password } = data
      return new Promise((resolve, reject) => {
        login(username, password).then(res => {
          commit('setUser', res)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },
    logout({state, commit}) {
      return new Promise((resolve, reject) => {
        logout(state.token).then(() => {
          commit('removeUser')
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    }
  }
}

export default user

以上我们单独创建一个用户模块来维护和用户相关状态,分模块管理的方式对于中大型应用可以清晰地维护相关状态信息。登录和退出登录接口设计异步操作,所有我们定义在actions选项中。

注册模块

store/index.js

js 复制代码
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    user
  },
  state: {},
  mutations: {}
})

export default store

user.js模块引入到store跟实例的modules对象中。注册后,对于user模块的选项定义属性值,会和合并到store根实例中。如果需要独立隔离命名空间 ,可在user模块中添加属性namespaced: true

js 复制代码
// user.js
const user = {
  namespaced: true,
  ...
}

创建插件

store/plugins/storage.js

js 复制代码
import { setStorage, removeStorage, getStorage } from '@/utils/storage'
import { USER_KEY } from '@/utils/constant'

// 当 store 初始化后调用
const storage = store => {
  console.log('初始化')
	// 获取缓存的用户信息
  const user = getStorage(USER_KEY)
  // 用户存在,初始化用户信息
  user && store.commit('setUser', user)
  // 监听commit方法的执行
	store.subscribe((mutation, state) => {
    if(mutation.type === 'setUser') {
      setStorage(USER_KEY, state.user)
    } else if(mutation.type === 'removeUser') {
      removeStorage(USER_KEY)
    }
	})
}

export default storage;

以上我们创建了一个storage插件,用于对用户登录信息进行本地持久化和初始化。当store初始化时会调用该方法,并且参数会返回初始化后的store对象。

我们可以在该方法中对用户信息进行初始化,以及监听当执行更新用户信息的mutations方法时,自动更新本地缓存的用户信息。

引入到store跟实例并注册插件

js 复制代码
// store.js
const store = new Vuex.Store({
  // 注册插件
  plugins: [storage],
  modules: {
    user
  }
})

缓存方法封装

以下使用的时uniapp提供的本地缓存api

utils/storage.js

js 复制代码
export const setStorage = (key, data) => {
  uni.setStorageSync(key, data)
}

export const removeStorage = (key) => {
  uni.removeStorageSync(key)
}

export const getStorage = (key) => {
  const data = uni.getStorageSync(key)
  return data
}

以上我们对缓存方法的封装的目的是便于后续进行扩展,比如:

1.同一域名下如果存在多个项目,则当缓存的key属性相同时,可能会造成多个项目之间的数据污染 ,这时可在可在缓存前增加一个 项目名称前缀 等方式包装key得唯一性。

2.需要设置key的有效时间时,可以把字段包装成一个包含缓存时间的对象进行缓存。

3.当需要对缓存数据进行加密时。

4.当你要切换缓存api时。

5.其他扩展...

总结

以上通过一个简单的用户登录的例子来展开叙述,通过vuex中的modules选项对用户相关状态进行分模块维护,使用plugins选项注册一个插件,用来保证vuex中的用户状态信息和本地的缓存用户信息进行通过,在使用缓存相关api时,建议统一进行封装,便于后续项目扩展。

相关推荐
秦jh_9 分钟前
【Linux】多线程(概念,控制)
linux·运维·前端
蜗牛快跑21322 分钟前
面向对象编程 vs 函数式编程
前端·函数式编程·面向对象编程
Dread_lxy23 分钟前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
涔溪1 小时前
Ecmascript(ES)标准
前端·elasticsearch·ecmascript
榴莲千丞1 小时前
第8章利用CSS制作导航菜单
前端·css
奔跑草-1 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
guokanglun2 小时前
CSS样式实现3D效果
前端·css·3d
咔咔库奇2 小时前
ES6进阶知识一
前端·ecmascript·es6
前端郭德纲2 小时前
浏览器是加载ES6模块的?
javascript·算法