From 2b5c7d4a9c029563cc789318b0b199eda6822b57 Mon Sep 17 00:00:00 2001 From: lbwa Date: Sat, 7 Mar 2020 17:59:11 +0800 Subject: [PATCH] feat(store): don't use replaceState anymore replaceState API wouldn't trigger vue-devtool --- src/plugins/store.ts | 18 +++++++++--------- src/store/global.ts | 39 +++++++++++++++++++++++++++++++-------- src/store/index.ts | 2 +- src/store/modules/user.ts | 2 +- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/plugins/store.ts b/src/plugins/store.ts index de99fdc..10a7184 100644 --- a/src/plugins/store.ts +++ b/src/plugins/store.ts @@ -2,13 +2,13 @@ import { Plugin } from 'vuex' import { RootState } from '@/store/global' import cloneDeep from 'lodash.clonedeep' -export const createResetPlugin: ( - listenType: string -) => Plugin = listenType => store => { - const stateClone = cloneDeep(store.state) - - store.subscribeAction(action => { - if (action.type !== listenType) return - store.replaceState(stateClone) - }) +/** + * For storing the whole initial `store.state` including all modules states + * @when This plugin will be called only once in the whole Store instance lifetime + * @see https://github.com/vuejs/vuex/blob/v3.1.2/src/store.js#L64-L65 + */ +export const createResetPlugin: () => Plugin = () => store => { + const clone = cloneDeep(store.state) + delete clone.DO_NOT_MUTATE + store.commit('setSnapshot', clone) } diff --git a/src/store/global.ts b/src/store/global.ts index 83825b4..219be3a 100644 --- a/src/store/global.ts +++ b/src/store/global.ts @@ -1,17 +1,40 @@ -export type RootState = {} +import { GetterTree, MutationTree, ActionTree } from 'vuex' +import cloneDeep from 'lodash.clonedeep' -const globalNamespace = { - state: {} as RootState, +export type RootState = { + DO_NOT_MUTATE: RootState +} + +interface GlobalNamespaces { + state: RootState + getters: GetterTree + mutations: MutationTree + actions: ActionTree +} + +const globalNamespace: GlobalNamespaces = { + state: { + // DO NOT mutate this snapshot property for the entire store.state + // This is should be use to reset state + DO_NOT_MUTATE: {} as RootState + }, getters: {}, - mutations: {}, + mutations: { + // should always pass a store.state deep clone, instead of reference + setSnapshot(state, snapshot) { + state.DO_NOT_MUTATE = snapshot + }, + resetState(state, replacement: RootState) { + // should always use a deep clone from snapshot to avoid unexpected snapshot mutation + Object.assign(state, cloneDeep(replacement)) + } + }, actions: { - resetStore() { - /** - * This action will trigger store reset plugin in src/plugins/store.ts - */ + resetState({ commit, rootState }) { + commit('resetState', rootState.DO_NOT_MUTATE) } } } diff --git a/src/store/index.ts b/src/store/index.ts index 66623bc..cbeecd4 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -9,7 +9,7 @@ import { createResetPlugin } from '../plugins/store' Vue.use(Vuex) const plugins = (() => { - const plugins = [createResetPlugin('resetStore')] + const plugins = [createResetPlugin()] if (__DEV__) { plugins.push(createLogger()) } diff --git a/src/store/modules/user.ts b/src/store/modules/user.ts index 0cdb821..938037a 100644 --- a/src/store/modules/user.ts +++ b/src/store/modules/user.ts @@ -100,7 +100,7 @@ const user: Module = { }, async logout({ dispatch }, router: VueRouter) { reset(router) - await dispatch('resetStore', null, { root: true }) + await dispatch('resetState', null, { root: true }) router.push({ name: 'Login' })