如何在 Vuex 2 中设置初始状态?
Posted
技术标签:
【中文标题】如何在 Vuex 2 中设置初始状态?【英文标题】:How do I set initial state in Vuex 2? 【发布时间】:2017-06-09 16:42:39 【问题描述】:我正在为一个小型应用程序使用 Vue.js 2.0 和 Vuex 2.0。我正在通过调用从 API 检索初始状态的操作来在根 Vue 实例上的“已创建”生命周期挂钩中初始化存储......就像在我的 根组件 中一样:
const app = new Vue(
el: "#app",
router,
store,
data:
vacation: ,
,
components:
'vacation-status': VacationStatus,
,
created()
//initialize store data structure by submitting action.
this.$store.dispatch('getVacation');
,
computed:
,
methods:
);
这工作得很好。这是我在此处调用的商店中的操作:
getVacation(commit)
api.getVacation().then(vacation => commit(UPDATE_VACATION, vacation))
使用“UPDATE_VACATION”提交的突变在这里:
[UPDATE_VACATION] (state, payload)
state.vacation = payload.vacation;
,
我的问题:当我加载应用程序时,我所有从商店“获取”值的组件都会抛出错误,我正试图访问商店中的“未定义”值。换句话说,状态还没有被初始化。
例如,我有一个在 子组件 中有 getter 的组件,如下所示:
computed:
arrival ()
return this.$store.getters.arrival
,
departure()
return this.$store.getters.departure
,
countdown: function()
return this.$store.getters.countdown
所有这些 getter 都会导致错误,因为在状态对象上未定义“假期”。这对我来说似乎是一个异步问题,但可能是错误的。 我是否在错误的位置初始化了我的商店状态?
Vue.use(Vuex);
export default new Vuex.Store(
state: ,
getters:
getVacation: state =>
return state.vacation
,
guests: state =>
return state.vacation.guests
,
verifiedGuests: state =>
return state.vacation.guests.filter(guest => guest.verified)
,
emergencyContacts: state =>
return state.emergency_contacts
,
arrival: state =>
return state.vacation.check_in
,
departure: state =>
return state.vacation.check_out
,
countdown : state =>
let check_in = new Date(state.vacation.check_in);
let now = new Date();
if ((now - check_in) > 0)
return 'This vacation started on ' + check_in;
let difference = check_in - now;
let day = 1000 * 60 * 60 * 24;
return Math.ceil(difference / day) + " days until your vacation";
,
mutations:
[UPDATE_VACATION] (state, payload)
state.vacation = payload.vacation;
,
[ADD_GUEST] (state, payload)
state.vacation.guests.push(payload.guest);
,
[REMOVE_GUEST] (state, payload)
state.vacation.guests.filter(guest => debugger; return guest.id != payload.guest.id)
,
[UPDATE_GUEST] (state, payload)
state.vacation.guests.map(guest =>
// Refactor Object.assign to deep cloning of object
return guest.id === payload.guest.id ? Object.assign(, guest, payload.guest) : guest;
)
,
[ADD_EMERGENCY] (state, payload)
state.vacation.emergency_contacts.push(payload.emergency_contact)
,
[REMOVE_EMERGENCY] (state, payload)
state.vacation.emergency_contacts.filter(contact => contact.id !== payload.emergency_contact.id)
,
[UPDATE_EMERGENCY] (state, payload)
state.vacation.emergency_contacts.map(contact =>
// Refactor not needed because emergency_contact is a shallow object.
return contact.id === payload.emergency_contact.id ? Object.assign(, contact, payload.emergency_contact) : contact;
);
,
actions:
getVacation(commit)
api.getVacation().then(vacation => commit(UPDATE_VACATION, vacation))
,
addGuest(commit, guest)
commit(ADD_GUEST, guest);
,
removeGuest(commit, guest)
commit(REMOVE_GUEST, guest);
,
updateGuest(commit, guest)
commit(UPDATE_GUEST, guest);
,
addEmergency(commit, guest)
commit(ADD_EMERGENCY, contact)
,
removeEmergency(commit, contact)
commit(REMOVE_EMERGENCY, contact)
,
updateEmergency(commit, contact)
commit(UPDATE_EMERGENCY, contact)
,
updateServer(store, payload)
return api.saveVacation(payload)
);
只是为了让其他人清楚解决方案:
我没有在商店本身中正确设置我的初始状态。我正在提取数据并正确更新商店,但商店需要像这样初始化:
export default new Vuex.Store(
state:
vacation: //I added this, and then justed updated this object on create of the root Vue Instance
,
);
【问题讨论】:
【参考方案1】:您可以创建一个返回初始状态的函数,并将其用于您的 Vuex 实例,如下所示:
function initialStateFromLocalStorage()
...
const empty =
status: '',
token: '',
user: null
return empty;
export default new Vuex.Store(
state: initialStateFromLocalStorage,
...
只要您返回一个状态对象,您就可以在该函数中做任何您想做的事情,对吧?
【讨论】:
在不能直接改变状态的严格模式下不起作用。【参考方案2】:我认为你做的一切都是对的。也许您只是没有正确创建吸气剂(在您的代码中看不到任何定义)。或者您的初始状态设置不正确(在您的 sn-p 中也不可见)。
我会使用mapState
让组件中的状态属性可用。
在演示中,只需将users
添加到mapState
方法参数的数组中,用户数据将在组件中可用。 (我刚刚添加了 getter users
来展示它是如何工作的。如果您使用的是 mapState,则不需要这样做。)
请看下面的演示或fiddle。
const api =
'https://jsonplaceholder.typicode.com/users'
const UPDATE_USERS = 'UPDATE_USERS'
const SET_LOADING = 'SET_LOADING'
const store = new Vuex.Store(
state:
users: ,
loading: false
,
mutations:
[UPDATE_USERS](state, users)
console.log('mutate users', users)
state.users = users;
console.log(state)
, [SET_LOADING](state, loading)
state.loading = loading;
,
getters:
users(state)
return state.users
,
actions:
getUsers(commit)
commit(SET_LOADING, true);
return fetchJsonp(api)
.then((users) => users.json())
.then((usersParsed) =>
commit(UPDATE_USERS, usersParsed)
commit(SET_LOADING, false)
)
)
const mapState = Vuex.mapState;
const Users =
template: '<div><ul><li v-for="user in users">user.name</li></ul></div>',
computed: mapState(['users'])
new Vue(
el: '#app',
store: store,
computed:
...mapState(['loading']),
//...mapState(['users']),
/*users () // same as mapState
return this.$store.state.users;
*/
users() // also possible with mapGetters(['users'])
return this.$store.getters.users
,
created()
this.$store.dispatch('getUsers')
,
components:
Users
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch-jsonp/1.0.5/fetch-jsonp.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.1.1/vuex.min.js"></script>
<div id="app">
<div v-if="loading">loading...</div>
<users></users>
<pre v-if="!loading">users</pre>
</div>
【讨论】:
感谢您的回复!我没有在根 Vue 实例中包含任何吸气剂,因为我在根的子组件中声明了所有吸气剂。那样可以么?或者我是否需要像您在小提琴中所做的那样,在与“创建”生命周期方法挂钩的同一实例中声明我的 getter? 我包括了我的整个商店,再次感谢您的帮助 不客气。在组件中添加 getter 是可以的。您可以在计算道具中添加吸气剂。你的组件。对于您的更新:我会将假期添加到您的状态对象中。喜欢这个state: vacation:
。我认为这是让反应性道具工作所必需的。
所以我最近改变了很多东西,但我回去仔细测试了你提到的state: vacation:
...修复了它。这真的很令人沮丧,但我很高兴我明白了。感谢您的帮助!以上是关于如何在 Vuex 2 中设置初始状态?的主要内容,如果未能解决你的问题,请参考以下文章