开发者问题收集

在 vuex 中从 firebase 读取数据

2020-04-02
2412

我是 Vue Js 的新手。我正在做一个 TODO Web 应用程序。我使用 firebase 作为后端和数据库。我正在使用 Vuex 进行状态管理。到目前为止,我能够将数据添加到 firebase,但是当需要读取时,我被卡住了。我无法从 firebase 读取数据。 它在我调用的 component 中显示一个空数组。

这是我显示数组值的地方 这是我的 store.js

import Vue from 'vue';
import Vuex from 'vuex';
import firebase from "firebase";


Vue.use(Vuex);

export const store = new Vuex.Store({

    state:{
        events:[],
        error:''
    },

    mutations:{
        setEvent(state){
            let items = [];

            firebase.database().ref('eventos')
                .on('value',event =>{
                    event.forEach(data =>{
                        items.push(data.val())
                    })
                });

            state.events = items
        },

        setError(state, payload) {
            state.error = payload;
        },

    },

    actions:{
        addEvent(context,payload){

            firebase.database().ref('eventos/').push(payload)
                .then((event)=>{
                    context.commit('setEvent',event)
                }).catch(err =>{
                console.log(err)
            })
        },
    },

    getters:{
        eventList: state => {
            return state.events
        }
    }



});

在这个组件中,我调用数组事件来显示所有值

<template>
    <div>
        {{eventList}}
    </div>
</template>

<script>
    export default {
        name: "ReadEvents",

        computed:{
            eventList(){
                return this.$store.getters.eventList;
            }
        }
    }
2个回答

数据是从 Firebase 异步加载的。在此过程中,您的主代码将继续运行,因此 UI 不会被阻止。然后,一旦数据可用,您的回调就会使用该数据调用。

最简单的方法是放置一些日志语句来查看这一点:

setEvent(state){
    console.log("Before starting to load data");
    firebase.database().ref('eventos')
    .on('value',event =>{
      console.log("Got data");
    });

    console.log("After starting to load data");
},

当您运行此代码时,它会记录:

Before starting to load data

After starting to load data

Got data

虽然这可能不是您所期望的,但它完全解释了为什么您的数据没有显示。当您调用 setState 时, items 尚未填充。

要解决此问题,请将您的 setState 调用移至 on() 回调中:

setEvent(state){
    firebase.database().ref('eventos')
    .on('value',event =>{
        let items = [];
        event.forEach(data =>{
            items.push(data.val())
        })
        state.events = items
    });
},

与当前问题无关,我强烈建议您还将 data.key 存储在数组中,因为当您需要从数据库中的数组中查找项目时,您一定会需要它。

例如,该代码可能是:

event.forEach(data =>{
    items.push({ "$id": data.key, ...data.val() })
})

因此,密钥存储在 $id 中,而所有其他属性均按原样复制。

Frank van Puffelen
2020-04-03

首先,您不应尝试在 vuex 突变中执行任何异步代码,请参阅 https://vuex.vuejs.org/guide/mutations.html#mutations-must-be-synchronous

相反,应将逻辑包含在您的操作中,并且仅在您拥有要提交给状态的数据时才调用突变。类似这样的内容:

export const store = new Vuex.Store({
    state: {
        events: [],
        error: ''
    },

    mutations: {
        setEvents (state, events) {
            state.events = events;
        },

        setError (state, payload) {
            state.error = payload;
        }
    },

    actions: {
        addEvent ({ commit }, event) {
            firebase.database().ref('eventos').push(event)
            .then(() => {
                firebase.database().ref('eventos')
                .on('value', data => {
                    const events = data.map(item => { 
                        return { "$id": item.id, ...item.val() };
                    });
                    commit('setEvents', events);
                });
            })
            .catch(err => {
                console.log(err);
            })
        },
    },

    getters:{
        eventList: state => {
            return state.events;
        }
    }
});
Paul Renshaw
2020-04-03