Как очистить состояние в магазине vuex?

Мое состояние в хранилище vuex огромно.

Есть ли способ reset всех данных в состоянии за один раз, вместо того, чтобы вручную установить все на null?

Ответ 1

Я только что нашел отличное решение, которое работает для меня.

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
}

Сбросить состояние модуля Vuex как профессионал

Спасибо Таха Шаштари за отличное решение.

Майкл,

Ответ 2

Обновите после использования приведенного ниже решения немного больше

Таким образом, получается, что если вы используете 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);

Обновление (из комментариев). Что делать, если нужно сбросить/определить только один модуль и оставить остальные как есть?

Если вы не хотите сбрасывать все свои модули, вы можете просто сбросить нужные вам модули и оставить другой сброс в их текущем состоянии.

Например, скажем, у вас есть несколько модулей, и вы только хотите вернуть модуль a в его начальное состояние, используя метод выше ^, который мы назовем resetStateA. Затем вы должны клонировать исходное состояние (которое включает в себя все модули перед сбросом).

var currentState = deepClone(this.state)

где deepClone - ваш метод глубокого клонирования (у lodash есть хороший). Этот клон имеет текущее состояние перед сбросом. Итак, давайте переписать это

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

и используйте это новое состояние с replaceState, которое включает текущее состояние всех ваших модулей, кроме модуля a с его начальным состоянием:

this.$store.replaceState(newState);

Оригинальное решение

Я нашел этот удобный метод в Vuex.store. Вы можете быстро и безболезненно очистить все состояния с помощью replaceState, например:

store.replaceState({})

Он работает с одним хранилищем или с модулями и сохраняет реактивность всех свойств вашего состояния. См. страницу документа Vuex api и найдите страницу для replaceState.

Для модулей

Если вы заменяете магазин модулями, вам нужно будет включать пустые объекты состояния для каждого модуля. Так, например, если у вас есть модули a и b, вы должны сделать:

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

Ответ 3

Вы можете объявить начальное состояние и reset это свойство этого свойства по свойству. Вы не можете просто сделать 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])
       }
    }
}

Ответ 4

Если вы выполните состояние = {}, вы удалите реактивность свойств, и ваши мутации с геттерами перестанут работать.

у вас может быть суб-свойство вроде:

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
}

Ответ 5

Я не уверен, что вы используете, но мне нужно было сделать что-то подобное. Когда пользователь выходит из системы, я хочу очистить все состояние приложения, поэтому я просто сделал window.reload. Возможно, не совсем то, что вы просили, но если вы хотите очистить магазин, возможно, альтернативу.

Ответ 6

На основе этих 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 ниже для 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>

Ответ 7

Вызовите router.go() или this.$router.go()

Это обновит страницу, и ваше состояние будет сброшено до того состояния, которое было, когда пользователь впервые загрузил приложение.

Ответ 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

Вот решение, которое работает в моем приложении. Я создал файл с именем 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,
});

и что это

Ответ 10

Я прочитал выше и реализовал решение. может помочь и вам !!

Все объекты, хранящиеся в Vue, действуют как наблюдаемая. Таким образом, если ссылка значения изменена/изменена, это приведет к изменению фактического значения.

Итак, чтобы сбросить состояние, исходные модули хранения должны быть скопированы как значение.

При выходе пользователя из системы одно и то же значение должно быть назначено для каждого модуля как копия.

Это может быть достигнуто следующим образом:

Шаг 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);
    });
};