Vuex重置store的方法记录

Vue项目中使用Vuex作为状态管理已经是比较通用的做法了,Vuex本质上类似全局的变量存储,方便在所有Vue组件中共享,而且也可以动态改变状态。

目前使用Vuex可以把登录数据保存到localStorage中,实现短时间内免登陆。

存储localStorage参考:Vue项目集成vuex-persistedstate

但是Vuex似乎没有考虑提供一个重置或者清空state的方法,需要自己来实现。

清理登录数据

​ 注销时需要清理store比较麻烦,store是在内存中,哪怕是删除localStorage,也可能再次把内存中的store数据写入localStorage,造成注销失败。

直接删除localStorage

可以直接删除localStorage,删除后还需要刷新页面,似乎体验不是很好,整个页面会刷新。

window.localStorage.removeItem(STORAGE_KEY)
window.location.reload()

重置store

还是考虑从store下手,重置store的思路如下:

  1. store初始化的时候把store中的初始state存下来
  2. actionsmutations增加一个重置(__resetStoreState)方法,并把重置方法名称保存到重置方法列表
  3. 如果有子模块,递归处理子模块,重复第2步骤
  4. 提供一个外部访问的重置方法,具体逻辑就是把重置方法列表中的重置方法触发一下。
具体实现

具体代码如下(StoreHelper.js),依赖lodash库:

import cloneDeep from 'lodash/cloneDeep'
import store from '@/store'
import Vuex from 'vuex'
const TO_RESET_STORE_STATE_KEYS = [] // 需要清理的Key
const RESET_STORE_STATE_KEY = '__resetStoreState' // 内部清理方法名
/**
 * store重置初始化,递归处理子模块,并把需要重置的key保存下来
 *
 * @param configData store数据
 * @param excludeNames 不清理的模块名,有些数据可能需要在注销时也不清理
 * @param parentModuleKey 模块名拼接,处理子模块
 */
export function $createStoreWithResetHandler (configData, excludeNames = [], parentModuleKey = '') {
  const resetStoreKey = parentModuleKey ? `${parentModuleKey}/${RESET_STORE_STATE_KEY}` : RESET_STORE_STATE_KEY
  TO_RESET_STORE_STATE_KEYS.push(resetStoreKey) // reset相关key存入数组中
  if (configData.modules) {
    Object.keys(configData.modules).forEach(moduleName => {
      if (excludeNames.indexOf(moduleName) === -1) {
        const module = configData.modules[moduleName]
        const newParentModuleKey = parentModuleKey ? `${parentModuleKey}/${moduleName}` : moduleName
        $createStoreWithResetHandler(module, excludeNames, newParentModuleKey)
      }
    })
  }
  if (configData.state) {
    configData.mutations = configData.mutations || {}
    configData.actions = configData.actions || {}
    if (!configData.mutations[RESET_STORE_STATE_KEY]) {
      const initialState = cloneDeep(configData.state)
      configData.mutations[RESET_STORE_STATE_KEY] = state => Object.assign(state, cloneDeep(initialState))
    }
    if (!configData.actions[RESET_STORE_STATE_KEY]) {
      configData.actions[RESET_STORE_STATE_KEY] = ({ commit }) => commit(RESET_STORE_STATE_KEY)
    }
  }
  return configData
}
/**
 * 重置store方法
 *
 * @returns Promise
 */
export function $resetStoreState () { // 需要重置的key已经存下来,循环key触发重置
  const resetResults = TO_RESET_STORE_STATE_KEYS.map(resetKey => store.dispatch(resetKey))
  return Promise.allSettled(resetResults)
}
/**
 * 包装store,方便使用
 *
 * @param configData
 * @param excludeNames
 * @returns {Store<unknown>}
 */
export function $wrapStore (configData, excludeNames = []) {
  return new Vuex.Store($createStoreWithResetHandler(configData, excludeNames))
}
/**
 * 导出$resetStoreState方法,方便使用
 * Vue.use(StoreHelper)
 */
export default {
  install: (Vue, options = {}) => Object.assign(Vue.prototype, { $resetStoreState })
}
包装store搜集数据

包装store搜集state数据,以及需要触发reset的相关方法

store.js默认代码(去掉import):

Vue.use(Vuex)
export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {
    Common: CommonStore,
    Theme: ThemeStore
  },
  plugins: [createPersistedState()]
})

修改代码也比较简单,把new Vuex.Store换成$wrapStore,如果部分模块不要reset,可以过滤掉:

Vue.use(Vuex)
Vue.use(StoreHelper)
export default $wrapStore({
  state: {},
  mutations: {},
  actions: {},
  modules: {
    Common: CommonStore,
    Theme: ThemeStore
  },
  plugins: [createPersistedState()]
}, ['Common']) // Common模块不要reset
触发store重置

在需要的地方触发一下重置,比如注销,然后跳转到登录页面即可

this.$resetStoreState().then(() => {
    // 跳转到登录页面
})

给TA打赏
共{{data.count}}人
人已打赏
运维

本地Elasticsearch安装配置

2024-11-19 10:38:03

运维

Calibre桌面版豆瓣插件升级

2024-11-19 10:38:10

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索