2016-11-03 101 views
1

我刚开始在这里学习Vuex。到目前为止,我一直在store.js文件中存储共享数据,并在每个模块中导入store,但这样会变得令人讨厌,而且我很担心变化状态。使用Vuex进行异步呼叫

我在苦苦挣扎的是如何使用Vuex从Firebase导入数据。根据我的理解,只有行为可以进行异步调用,但只有突变才能更新状态?

现在我正在从我的突变对象调用firebase,它似乎工作正常。老实说,所有的上下文,提交,调度等似乎有点过载。我希望能够使用必要的最低数量的Vuex来提高生产力。

在文档中,它看起来像我可以编写一些代码,用于更新像下面这样的突变对象中的状态,将它导入computed属性中的组件,然后使用store.commit('increment')触发状态更新。这似乎是使用Vuex所需的最低金额,但接下来的行动是在哪里进行的?困惑:(上的最佳方法任何帮助做到这一点或最佳实践,将不胜感激!

const store = new Vuex.Store({ 
    state: { 
    count: 0 
    }, 
    mutations: { 
    increment (state) { 
     state.count++ 
    } 
    } 
}) 

我的代码如下

store.js

import Vue from 'vue' 
import Vuex from 'vuex' 

Vue.use(Vuex); 

const db = firebase.database(); 
const auth = firebase.auth(); 

const store = new Vuex.Store({ 
    state: { 
    userInfo: {}, 
    users: {}, 
    resources: [], 
    postKey: '' 
    }, 
    mutations: { 

    // Get data from a firebase path & put in state object 

    getResources: function (state) { 
     var resourcesRef = db.ref('resources'); 
     resourcesRef.on('value', snapshot => { 
      state.resources.push(snapshot.val()); 
     }) 
    }, 
    getUsers: function (state) { 
     var usersRef = db.ref('users'); 
     usersRef.on('value', snapshot => { 
      state.users = snapshot.val(); 
     }) 
    }, 
    toggleSignIn: function (state) { 
     if (!auth.currentUser) { 
      console.log("Signing in..."); 
      var provider = new firebase.auth.GoogleAuthProvider(); 
      auth.signInWithPopup(provider).then(result => { 
      // This gives you a Google Access Token. You can use it to access the Google API. 
      var token = result.credential.accessToken; 
      // The signed-in user info. 
      var user = result.user; 
      // Set a user 
      var uid = user.uid; 
      db.ref('users/' + user.uid).set({ 
       name: user.displayName, 
       email: user.email, 
       profilePicture : user.photoURL, 
      }); 

      state.userInfo = user; 
      // ... 
      }).catch(error => { 
      // Handle Errors here. 
      var errorCode = error.code; 
      var errorMessage = error.message; 
      // The email of the user's account used. 
      var email = error.email; 
      // The firebase.auth.AuthCredential type that was used. 
      var credential = error.credential; 
      // ... 
      }); 
     } else { 
      console.log('Signing out...'); 
      auth.signOut();  
     } 
    } 
    } 
}) 

export default store 

main.js

import Vue from 'vue' 
import App from './App' 
import store from './store' 

new Vue({ 
    el: '#app', 
    store, // Inject store into all child components 
    template: '<App/>', 
    components: { App } 
}) 

App.vue

<template> 
    <div id="app"> 
    <button v-on:click="toggleSignIn">Click me</button> 
    </div> 
</template> 

<script> 

import Hello from './components/Hello' 


export default { 
    name: 'app', 
    components: { 
    Hello 
    }, 
    created: function() { 
    this.$store.commit('getResources'); // Trigger state change 
    this.$store.commit('getUsers'); // Trigger state change 
    }, 
    computed: { 
    state() { 
     return this.$store.state // Get Vuex state into my component 
    } 
    }, 
    methods: { 
    toggleSignIn() { 
     this.$store.commit('toggleSignIn'); // Trigger state change 
    } 
    } 
} 

</script> 

<style> 

</style> 

回答

12

所有的AJAX应该进入行动而不是突变。因此,这一进程将通过调用你的行动

...其承诺从AJAX回调数据的突变

...这是负责更新vuex状态开始。

参考:http://vuex.vuejs.org/en/actions.html

下面是一个例子:

// vuex store 

state: { 
    savedData: null 
}, 
mutations: { 
    updateSavedData (state, data) { 
    state.savedData = data 
    } 
}, 
actions: { 
    fetchData ({ commit }) { 
    this.$http({ 
     url: 'some-endpoint', 
     method: 'GET' 
    }).then(function (response) { 
     commit('updateSavedData', response.data) 
    }, function() { 
     console.log('error') 
    }) 
    } 
} 

然后打电话给你的AJAX,你必须现在做这个调用操作:

store.dispatch('fetchData') 

在你的情况下,只需将您的firebase ajax替换为this.$http({...}).then(...),然后在回调中调用您的操作即可。

+0

这是非常详细的诚实。为什么'fetchData'不能直接更新'saveDate'?突变看起来多余。 – Martian2049