Мое состояние в хранилище vuex огромно.
Есть ли способ reset всех данных в состоянии за один раз, вместо того, чтобы вручную установить все на null?
Мое состояние в хранилище vuex огромно.
Есть ли способ reset всех данных в состоянии за один раз, вместо того, чтобы вручную установить все на null?
Я только что нашел отличное решение, которое работает для меня.
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 как профессионал
Спасибо Таха Шаштари за отличное решение.
Майкл,
Таким образом, получается, что если вы используете 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: {}
})
Вы можете объявить начальное состояние и 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])
}
}
}
Если вы выполните состояние = {}, вы удалите реактивность свойств, и ваши мутации с геттерами перестанут работать.
у вас может быть суб-свойство вроде:
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
}
Я не уверен, что вы используете, но мне нужно было сделать что-то подобное. Когда пользователь выходит из системы, я хочу очистить все состояние приложения, поэтому я просто сделал window.reload
. Возможно, не совсем то, что вы просили, но если вы хотите очистить магазин, возможно, альтернативу.
На основе этих 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>
Вызовите router.go()
или this.$router.go()
Это обновит страницу, и ваше состояние будет сброшено до того состояния, которое было, когда пользователь впервые загрузил приложение.
Если вы хотите сбросить все состояние, вы можете использовать встроенный метод 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() }
}
}
Вот решение, которое работает в моем приложении. Я создал файл с именем 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,
});
и что это
Я прочитал выше и реализовал решение. может помочь и вам !!
Все объекты, хранящиеся в 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);
});
};