如何清除 vuex 商店中的状态?

Posted

技术标签:

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

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

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

【问题讨论】:

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

【讨论】:

以上是关于如何清除 vuex 商店中的状态?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Vuex 商店模块状态中访问“this”

如何在 Vuex 中清除间隔

如何清除#ngrx 中的状态?

Vuex 商店状态不更新屏幕/Vue-Native

如何在 Nuxt 中从另一个访问一个 Vuex 状态?

如何从 javascript/typescript 模块文件(导入/导出)访问 Vuex 商店?