【问题标题】:How to clear state in vuex store?如何清除 vuex 商店中的状态?
【发布时间】:2017-07-06 19:50:42
【问题描述】:

我在 vuex 商店的状态是巨大的。

有没有办法一次性重置所有状态数据,而不是手动将所有内容设置为空?

【问题讨论】:

  • 重置是指将其设置为初始状态?
  • 在我的情况下,清除数据与重置相同,因为我的商店最初是空的。
  • 只是我的 2 便士,但我实际上分解了状态并加载了我正在使用的任何“核心”组件特有的存储。您可以在运行时使用 webpack 的异步导入方法导入特定的商店,并将其分配给您的 Vue 实例。不需要本机“模块”的东西,而且对您的客户来说更苗条。
  • 为什么不使用@ianwalter/vuex-reset

标签: vue.js vuejs2 vuex


【解决方案1】:

如果您清除了完整的 vuex 商店使用:

sessionStorage.clear();

【讨论】:

    【解决方案2】:
    function initialState () {
      return { /* .. initial state ... */ }
    }
    
    export default {
      state: initialState,
    
      mutations: {
        reset (state) {
          // acquire initial state
          const s = initialState()
          Object.keys(s).forEach(key => {
            state[key] = s[key]
          })
        }
      }
    }
    

    这是官方推荐 issue

    【讨论】:

      【解决方案3】:

      你可以这样做

      index.js

      ...
      
      const store = new Vuex.Store({
          modules: {
             ...
          }
      })
      
      store.initialState = clone(store.state)
      
      store.resetState = () => {
          store.replaceState(store.initialState)
      }
      
      export default store
      

      其他地方

      this.$store.resetState()
      

      【讨论】:

        【解决方案4】:

        我刚刚找到了适合我的绝佳解决方案。

        const getDefaultState = () => {
          return {
            items: [],
            status: 'empty'
          }
        }
        
        // initial state
        const state = getDefaultState()
        
        const actions = {
          resetCartState ({ commit }) {
            commit('resetState')
          },
          addItem ({ state, commit }, item) { /* ... */ }
        }
        
        const mutations = {
          resetState (state) {
            // Merge rather than replace so we don't lose observers
            // https://github.com/vuejs/vuex/issues/1118
            Object.assign(state, getDefaultState())
          }
        }
        
        export default {
          state,
          getters: {},
          actions,
          mutations
        }
        

        感谢 Taha Shashtari 的出色解决方案。

        迈克尔,

        【讨论】:

        • 这是最好的解决方案
        • 优秀的方法。为什么需要使用Object.assign(state, getDefaultState()) 而不是state = getDefaultState()?另外,为什么要有一个函数getDefaultState 而不仅仅是一个变量defaultState
        • @hitautodestruct,有一个问题解释了为什么需要通过以下方式重置状态github.com/vuejs/vuex/issues/1118
        • @MichaelHorojanski 谢谢,我更新了您的答案,并附上了解释决定的小评论
        • 请注意state 可以是一个函数,所以只需在导出中使用state: getDefaultState 而不是调用getDefaultState()
        【解决方案5】:

        您可以通过小包装轻松解决问题:vuex-extensions

        查看CodeSandbox 上的示例。

        创建 Vuex.Store

        import Vuex from 'vuex'
        import { createStore } from 'vuex-extensions'
        
        export default createStore(Vuex.Store, {
          plugins: []
          modules: {}
        })
        
        存储重置为初始状态
        // Vue Component
        this.$store.reset()
        
        // Vuex action
        modules: {
          sub: {
            actions: {
              logout() {
                this.reset()
              }
            }
          }
        }
        

        【讨论】:

          【解决方案6】:

          这是适用于我的应用的解决方案。我创建了一个名为 defaultState.js 的文件。

          //defaultState.js
          //the return value is the same as that in the state
          const defaultState = () => {
              return {
                 items: [],
                 poles: {},
                 ...
              }
          }
          
          export default defaultState
          

          然后你想在哪里使用它

          //anywhere you want to use it
          //for example in your mutations.js
          //when you've gotten your store object do
          
          import defaultState from '/path/to/defaultState.js'
          
          let mutations = {
              ...,
              clearStore(state){
                  Object.assign(state, defaultState())
              },
          }
          
          export default mutations
          
          

          然后在你的 store.js 中

          import Vue from 'vue';
          import Vuex from 'vuex';
          
          import actions from './actions';
          import getters from './getters';
          import mutations from './mutations'; //import mutations
          import state from './state';
          
          Vue.use(Vuex);
          
          
          export default new Vuex.Store({
              actions,
              mutations,
              state,
              getters,
          });
          
          

          就是这样

          【讨论】:

          • 状态不能直接改变,但是像这样的解决方案可以放在一个突变中
          • 是的。我在突变中使用了我的
          • 好的,如果代码在突变中,我会支持你的解决方案:)
          • 更新@FrancescoVenturini
          【解决方案7】:

          我自己已阅读上述内容并实施了解决方案。也可以帮到你!!

          存储在 Vue 中的所有对象都充当可观察对象。因此,如果一个值的reference更改/变异,它会触发实际值也被更改

          因此,为了重置状态,必须将初始存储模块复制为值

          在用户注销时,必须为每个模块分配相同的值作为副本。

          这可以通过以下方式实现:

          第 1 步:创建初始模块的副本。

          // store.ts
          
          // Initial store with modules as an object
          export const initialStoreModules = {
              user,
              recruitment,
          };
          
          export default new Vuex.Store({
              /**
               * Assign the modules to the store 
               * using lodash deepClone to avoid changing the initial store module values
               */
              modules: _.cloneDeep(initialStoreModules),
              mutations: {
                  // reset default state modules by looping around the initialStoreModules
                  [types.RESET_STATE](state: any) {
                  _.forOwn(initialStoreModules, (value: IModule, key: string) => {
                      state[key] = _.cloneDeep(value.state);
                  });
                  },
              }
          });
          

          第 2 步:调用操作以将状态改变为初始状态。

          // user_action.ts
          const logout = ({ commit }: any) => {
              commit(types.LOGOUT_INIT);
              new UserProxy().logout().then((response: any) => {
                router.push({
                  name: 'login',
                });
                // reset the state
                commit(types.RESET_STATE);
              }).catch((err: any) => {
                commit(types.LOGOUT_FAIL, err);
              });
          };
          

          【讨论】:

            【解决方案8】:

            如果你想重置你的整个状态,你可以使用内置的replaceState 方法。

            给定 index.js 中设置的状态:

                const state = { user: '', token: '', products: [] /* etc. */ }
                const initialStateCopy = JSON.parse(JSON.stringify(state))
            
                export const store = new Vuex.Store({ state, /* getters, mutations, etc. */ })
            
                export function resetState() {
                  store.replaceState(initialStateCopy)
                }
            

            然后在你的 vue 组件(或任何地方)导入resetState

                import { resetState } from '@/store/index.js'
            
                // vue component usage, for example: logout
                {
                  // ... data(), computed etc. omitted for brevity
                  methods: {
                    logout() { resetState() }
                  }
                }
            

            【讨论】:

              【解决方案9】:

              致电router.go()this.$router.go()

              这将刷新页面,您的状态将重置为用户首次加载应用时的状态。

              【讨论】:

              • localStorage.clear(); this.$router.go();救了我!
              【解决方案10】:

              在使用以下解决方案后更新

              所以事实证明,如果你使用 replaceState 和一个空对象 ({}),你最终会因为你的状态道具消失而导致反应性变砖。所以本质上你必须实际重置状态中的每个属性,然后使用store.replaceState(resetStateObject)。对于没有模块的商店,您基本上会执行以下操作:

              let state = this.$store.state;
              let newState = {};
              
              Object.keys(state).forEach(key => {
                newState[key] = null; // or = initialState[key]
              });
              
              this.$store.replaceState(newState);
              

              更新(来自 cmets):如果只需要重置/定义一个模块并保持其余模块不变怎么办?

              如果您不想重置所有模块,您可以只重置您需要的模块,并将其他重置保留在当前状态。

              例如,假设您有多个模块,并且您只想将模块a 重置为其初始状态,使用上面的方法^,我们将其称为resetStateA。然后您将克隆原始状态(包括所有模块之前重置)。

              var currentState = deepClone(this.state)
              

              deepClone 是您选择的深度克隆方法 (lodash has a good one)。此克隆在重置之前具有 A 的当前状态。所以让我们覆盖它

              var newState = Object.assign(currentState, {
                a: resetStateA
              });
              

              并将新状态与 replaceState 一起使用,其中包括所有模块的当前状态,但模块 a 及其初始状态除外:

              this.$store.replaceState(newState);
              

              原解决方案

              我在Vuex.store 中找到了这个方便的方法。您可以使用replaceState 快速轻松地清除所有状态,如下所示:

              store.replaceState({})
              

              它适用于单个存储或模块,并且它保留了所有状态属性的反应性。查看Vuex api doc page,并在页面中找到replaceState

              对于模块

              如果您要用模块替换商店,则必须为每个模块包含空状态对象。因此,例如,如果你有模块 ab,你会这样做:

              store.replaceState({
                a: {},
                b: {}
              })
              

              【讨论】:

              • 出于某种原因,在我的情况下,For Modules 部分的代码需要重新加载页面才能重置所有内容。
              • Vue 建议仅将replaceState 用于时间旅行。如果只需要重置/定义一个模块并保持其余部分不变怎么办。怎么做呢?我尝试使用mutations,但如果没有被盯着看,就会抛出undefined
              • @KasparTr 我更新了答案以处理您的问题。希望对您有所帮助!
              • @seebiscuit 感谢您的更新。在这种情况下,是的,您正在用它的所有模块替换整个状态。我想我的问题是你如何优雅地只替换一个模块而保留其他模块。现在我通过突变来做到这一点。
              • 是的,@KasparTr,replaceState 的缺点是它需要所有模块状态。但是,如果您不希望每秒重复此操作多次,或者您的状态不是几兆字节大,那么您可以争辩说性能损失值得过程的可读性和大小。
              【解决方案11】:

              基于这 2 个答案 (#1#2) 我编写了一个可行的代码。

              Vuex的index.js我的结构:

              import Vue from 'vue'
              import Vuex from 'vuex'
              import createPersistedState from 'vuex-persistedstate'
              
              import { header } from './header'
              import { media } from './media'
              
              Vue.use(Vuex)
              
              const store = new Vuex.Store({
                plugins: [createPersistedState()],
              
                modules: {
                  header,
                  media
                }
              })
              
              export default store
              

              在每个模块中,我们需要将所有状态移动到单独的 var initialState 中,并在变异中定义一个函数 resetState,如下所示 media.js

              const initialState = () => ({
                stateOne: 0,
              
                stateTwo: {
                  isImportedSelected: false,
                  isImportedIndeterminate: false,
              
                  isImportedMaximized: false,
                  isImportedSortedAsc: false,
              
                  items: [],
              
                stateN: ...
                }
              })
              
              export const media = {
                namespaced: true,
              
                state: initialState, // <<---- Our States
              
                getters: {
                },
              
                actions: {
                },
              
                mutations: {
                  resetState (state) {
                    const initial = initialState()
                    Object.keys(initial).forEach(key => { state[key] = initial[key] })
                  },
                }
              
              }
              

              在 Vue 组件中我们可以像这样使用它:

              <template>
              </template>
              
              <script>
                import { mapMutations } from 'vuex'
              
                export default {
                  name: 'SomeName',
              
                  data () {
                    return {
                      dataOne: '',
                      dataTwo: 2
                    }
                  },
              
                  computed: {
                  },
              
                  methods: {
                    ...mapMutations('media', [ // <<---- define module
                      'resetState' // <<---- define mutation
                    ]),
              
                    logout () {
                      this.resetState() // <<---- use mutation
                      // ... any code if you need to do something here
                    }
                  },
              
                  mounted () {
                  }
                } // End of 'default'
              
              </script>
              
              <style>
              </style>
              

              【讨论】:

                【解决方案12】:

                我不确定您的用例是什么,但我必须做类似的事情。当用户注销时,我想清除应用程序的整个状态 - 所以我只是做了window.reload。也许不完全符合您的要求,但如果这就是您想要清空商店的原因,也许是另一种选择。

                【讨论】:

                • 这似乎是最简单的解决方案,因为我正在注销,所以在我看来,重新加载窗口以清除商店并路由到登录页面并没有什么害处。除非 vue 可以更简单地自动设置初始状态(在我的情况下为空 '' ),否则应该有类似这样的东西。$store.clear();
                • 取决于用例。这只会把一切都搞砸,如果我们正在执行“完全重置”(例如用户注销),我们并不真正关心保持反应性或状态(实际上,我们想摆脱一切)。
                • 我想你现在更愿意window.location.reload
                • 如果你使用 vuex-persistedstate 这将不起作用
                【解决方案13】:

                您可以声明一个初始状态并将其按属性重置为该状态属性。你不能只做 state = initialState 否则你会失去反应。

                这是我们在我正在开发的应用程序中的做法:

                let initialState = {
                    "token": null,
                    "user": {}
                }
                
                const state = Vue.util.extend({}, initialState)
                
                const mutations = {
                    RESET_STATE(state, payload) {
                       for (let f in state) {
                        Vue.set(state, f, initialState[f])
                       }
                    }
                }
                

                【讨论】:

                  【解决方案14】:

                  如果您执行 state = {},您将移除属性的反应性,并且您的 getter 突变将突然停止工作。

                  你可以有一个像这样的子属性:

                  state: {
                    subProperty: {
                      a: '',
                      lot: '',
                      of: '',
                      properties: '',
                      .
                      .
                      .
                    }
                  }
                  

                  执行 state.subProperty = {} 应该会有所帮助,而且不会失去反应性。

                  你不应该有一个太大的状态,把它们分解成不同的模块,然后像这样导入你的 vuex 存储:

                  import Vue from 'vue'
                  import Vuex from 'vuex'
                  import authorization from './modules/authorization'
                  import profile from './modules/profile'
                  
                  Vue.use(Vuex)
                  
                  export const store = new Vuex.Store({
                    modules: {
                      authorization,
                      profile
                    }
                  })
                  

                  现在在您的个人文件中:

                  // modules/authorization.js
                  import * as NameSpace from '../NameSpace'
                  import { someService } from '../../Services/something'
                  
                  const state = {
                    [NameSpace.AUTH_STATE]: {
                      auth: {},
                      error: null
                    }
                  }
                  
                  const getters = {
                    [NameSpace.AUTH_GETTER]: state => {
                      return state[NameSpace.AUTH_STATE]
                    }
                  }
                  
                  const mutations = {
                    [NameSpace.AUTH_MUTATION]: (state, payload) => {
                      state[NameSpace.AUTH_STATE] = payload
                    },
                  }
                  
                  const actions = {
                    [NameSpace.ASYNC_AUTH_ACTION]: ({ commit }, payload) => {
                      someService.login(payload.username, payload.password)
                        .then((user) => {
                          commit(NameSpace.AUTH_MUTATION, {auth: user, error: null})
                        })
                        .catch((error) => {
                          commit(NameSpace.AUTH_MUTATION, {auth: [], error: error})
                        })
                    }
                  }
                  
                  export default {
                    state,
                    getters,
                    mutations,
                    actions
                  }
                  

                  如果你想清除状态,你可以使用一个变异工具:

                  state[NameSpace.AUTH_STATE] = {
                    auth: {},
                    error: null
                  }
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-04-10
                    • 2018-05-19
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-12-21
                    • 2020-05-22
                    • 2020-09-14
                    相关资源
                    最近更新 更多