首页 文章

如何在Vuex 2中设置初始状态?

提问于
浏览
29

我正在为一个小应用程序使用Vue.js 2.0和Vuex 2.0 . 我正在通过调用从API检索初始状态的操作初始化根Vue实例上的'created'生命周期钩子中的存储....就像我的_489816中一样:

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;
},

My Problem: 当我加载应用程序时,所有来自商店的'getting'值的组件抛出错误我已经初始化了'm trying to access ' undefined ' values on the store. In other words, state hasn' .

例如,我有一个在 Child Components 中有getter的组件,如下所示:

computed: {
        arrival () {
            return this.$store.getters.arrival
        },
        departure() {
            return this.$store.getters.departure
        },
        countdown: function() {
            return this.$store.getters.countdown
        }
}

所有这些getter都会导致错误,因为在状态对象上未定义'vacation' . 对我来说这似乎是一个异步问题,但可能是错误的 . Am I initializing my store state in the wrong spot?

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 回答

  • 19

    我认为你做的一切都是正确的 . 也许你只是没有正确创建getter(在代码中看不到任何定义) . 或者您未正确设置初始状态(在您的代码段中也不可见) .

    我会使用 mapState 在组件中使用状态属性 .

    在演示中,只需在 mapState 方法参数中将 users 添加到数组中,用户数据将在组件中可用 . (我刚刚添加了getter users 以显示它是如何工作的 . 那's not needed if you'使用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>
    

相关问题