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

前言

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

了解vuex的modules和plugins选项

modules:用来解决当项目比较复杂时,单一的状态树所导致store对象变得臃肿所导致的维护困难问题,每个模块都可以拥有自己的state、mutation、action、getter选项。
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时,建议统一进行封装,便于后续项目扩展。

相关推荐
朝朝辞暮i12 小时前
C++ 第 25 课:getter / setter + this
java·javascript·c++
扶风ff12 小时前
求职笔试资料太散?用练题簿在线刷题,按岗位整理练习清单
前端·学习·小程序
蜗牛互联网12 小时前
Python接入Gemini 3.8 Flash实现票据视觉抽取与规则校验
java·javascript·网络·人工智能·python
浪浪山_大橙子12 小时前
公司里的 AI,终于不只会聊天:我用 GPT‑6 把企业工作伙伴开源了
前端·后端·面试
琹箐12 小时前
命令行调用接口
前端
可乐鸡翅yeah_12 小时前
AES‑128 加密 M3U8,IV 初始化向量新手容易踩坑
前端·网络·数据库·ffmpeg·音视频·m3u8在线
MetWeave13 小时前
机场天气的"广播系统":三种报文一次讲明白
前端
易朵朵13 小时前
CSS 格式化上下文
css·vue.js
xieter13 小时前
【技术精选】深入浅出现代前端渲染与性能优化实践指南 (2026-10-04)
前端·javascript
计算机魔术师13 小时前
Anthropic 密会宗教领袖谈 Claude 意识,OpenAI 为什么急眼
前端