2017-01-24 61 views
16

Używam Vue.js 2.0 i Vuex 2.0 dla małej aplikacji. Ja inicjowania sklep w „” haczyka utworzonego cyklu życia na głównym instancji Vue wywołując akcję, która pobiera stan początkowy z API .... jak to w moim okopowych Komponentu:Jak ustawić stan początkowy w Vuex 2?

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: { 
} 
}); 

To działa dobrze. Oto działania w moim sklepie, że dzwonię tutaj:

getVacation({commit}){ 
    api.getVacation().then(vacation => commit(UPDATE_VACATION, vacation)) 
} 

Mutacja, że ​​dopuszcza się „UPDATE_VACATION” jest tutaj:

[UPDATE_VACATION] (state, payload) { 
    state.vacation = payload.vacation; 
}, 

Mój problem: Kiedy załadować app, wszystkie moje składniki, które "pobierają" wartości z błędów składowania sklepu próbuję uzyskać dostęp do "niezdefiniowanych" wartości w sklepie. Innymi słowy, stan nie został jeszcze zainicjowany.

Na przykład, mam komponent, który ma pobierające w Components dziećmi tak:

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

Wszystkie te getters powodować błędy ponieważ „wakacje” jest niezdefiniowana na obiekcie państwowej. Wydaje mi się, że jest to problem asynchroniczny, ale może być błędny. Czy inicjuję mój stan sklepu w niewłaściwym miejscu?

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) 
    } 
} 

});

nie zachodziło mój stan inital całkiem poprawnie w samym sklepie:

Tak więc rozwiązanie jest oczywiste dla innych. Wciągnąłem dane i zaktualizowałem poprawnie sklep, ale sklep musiał zostać zainicjowany w ten sposób:

export default new Vuex.Store({ 
state: { 
    vacation: {}//I added this, and then justed updated this object on create of the root Vue Instance 
}, 
}); 

Odpowiedz

13

Myślę, że wszystko robisz dobrze. Być może po prostu nie tworzysz poprawnie pobierających (nie widzisz żadnej definicji w twoim kodzie). Lub ustawienie niewłaściwego stanu początkowego (również niewidoczne w twoim fragmencie).

Chciałbym użyć mapState, aby właściwości stanu były dostępne w komponentach.

W wersji demonstracyjnej po prostu dodaj users do tablicy parametrów metody mapState, a dane użytkowników będą dostępne w komponencie. (Właśnie dodałem getter users, aby pokazać, jak to działa.) Nie jest to konieczne, jeśli używasz mapState.)

Proszę spojrzeć na wersję demo poniżej lub na tę 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 
 
     \t 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>

+0

Dzięki za odpowiedzi! Nie uwzględniłem żadnych elementów pobierających w głównej instancji Vue, ponieważ deklaruję wszystkie moje elementy pobierające w elementach potomnych tego katalogu głównego. Czy to w porządku? Czy muszę zadeklarować moje moduły pobierające w tej samej instancji, którą podłączam do "stworzonej" metody cyklu życia, tak jak robiłeś to w skrzypcach? – calbear47

+0

Zawarłem cały mój sklep, jeszcze raz dziękuję za pomoc – calbear47

+0

Nie ma za co.Można dodać moduły pobierające w komponentach. Możesz dodać moduły pobierające w rekwiacie obliczonym. swoich komponentów. Do twojej aktualizacji: Dodałbym wakacje do twojego obiektu stanu. Tak jak ten "stan: {wakacje: {}}". Myślę, że wymagane jest działanie reaktywnych rekwizytów. – AWolf