我正在为一个小应用程序使用Vue.js 2.0和Vuex 2.0.我正在通过调用从API检索初始状态的操作初始化根Vue实例上的'created'生命周期钩子中的存储....就像在我的根组件中一样:
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都会导致错误,因为状态对象上的'vacation'未定义.对我来说这似乎是一个异步问题,但可能是错误的.我是否在错误的位置初始化我的商店状态?
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 }, });
AWolf.. 25
我认为你做的一切都是正确的.也许你只是没有正确创建getter(在代码中看不到任何定义).或者您未正确设置初始状态(在您的代码段中也不可见).
我会使用mapState
组件中的状态属性.
在演示中,只需users
在mapState
方法参数中添加数组,用户数据将在组件中可用.(我刚刚添加了getter users
来展示它是如何工作的.如果你使用的是mapState,那就不需要了.)
请看下面的演示或这个小提琴.
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: '- {{user.name}}
',
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
}
})
loading...
{{users}}
我认为你做的一切都是正确的.也许你只是没有正确创建getter(在代码中看不到任何定义).或者您未正确设置初始状态(在您的代码段中也不可见).
我会使用mapState
组件中的状态属性.
在演示中,只需users
在mapState
方法参数中添加数组,用户数据将在组件中可用.(我刚刚添加了getter users
来展示它是如何工作的.如果你使用的是mapState,那就不需要了.)
请看下面的演示或这个小提琴.
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: '- {{user.name}}
',
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
}
})
loading...
{{users}}