如何使用Vue与VueFire加载Firebase数据?解决异步渲染问题
解决Vue等待Firebase异步数据加载的问题
哈哈先别冲动删问题或者辞职!这个异步数据加载的坑很多人都踩过,咱们马上给你理顺~
你的核心问题是:Firebase数据是异步获取的,Vue组件mounted钩子执行时,数据还没从Firebase返回,所以this.location还是空值,导致你赋值leftCoord和topCoord失败。下面给你几个实用的解决方案,附带修改后的完整代码:
方案一:利用Vuefire的响应式绑定(最省心)
Vuefire已经帮你把Firebase的数据变成了响应式的,你可以直接在模板里绑定location的属性,不用单独在data里存leftCoord和topCoord,同时用v-if确保数据加载完成后再渲染marker:
<template> <div id="app"> <!-- 只有location存在时才渲染marker,避免undefined错误 --> <span id="marker" class="fas fa-times" v-if="location" :style="{ left: `${location.leftCoord}px`, top: `${location.topCoord}px` }" ></span> <img @click="saveCoordinates($event)" src="./assets/parking-lot.jpg"> </div> </template> <script> import firebase from 'firebase' import { VueFire } from 'vuefire' import Vue from 'vue' // 别忘了安装Vuefire插件! Vue.use(VueFire) const config = { apiKey: 'MY-API-KEY', authDomain: 'MY-APP.firebaseapp.com', databaseURL: 'https://MY-APP.firebaseio.com', projectId: 'MY-APP', storageBucket: 'MY-APP.appspot.com', messagingSenderId: '1234567890' } const app = firebase.initializeApp(config) const db = app.database() const locationRef = db.ref('location') export default { name: 'app', // Vuefire自动绑定location数据,数据更新时组件自动响应 firebase: { location: locationRef }, data () { return { // 不需要单独存left/top坐标,直接用location的属性即可 } }, methods: { saveCoordinates: function (clickEvent) { const coordinates = { leftCoord: clickEvent.layerX, topCoord: clickEvent.layerY } // 直接用locationRef更新数据,Vuefire会自动同步到this.location locationRef.set(coordinates) } } } </script>
方案二:用watch监听数据变化
如果你还是想把坐标存在自己的data属性里,可以用Vue的watch监听location的变化,当数据从Firebase返回时再赋值:
<script> // ... 其他代码不变 ... export default { name: 'app', firebase: { location: locationRef }, data () { return { leftCoord: '', topCoord: '' } }, // 监听location的变化,数据加载完成后自动赋值 watch: { location(newLocation) { if (newLocation) { // 确保数据存在,避免空值赋值 this.leftCoord = newLocation.leftCoord this.topCoord = newLocation.topCoord } } }, methods: { saveCoordinates: function (clickEvent) { const coordinates = { leftCoord: clickEvent.layerX, topCoord: clickEvent.layerY } locationRef.set(coordinates) } } } </script>
方案三:手动监听Firebase数据事件
如果不想依赖Vuefire的自动绑定,也可以直接在mounted里监听Firebase的value事件,确保数据加载完成后再更新组件:
<script> // ... 其他代码不变 ... export default { name: 'app', data () { return { leftCoord: '', topCoord: '' } }, mounted () { // 手动监听Firebase数据变化,每次数据更新都会触发回调 locationRef.on('value', (snapshot) => { const locationData = snapshot.val() if (locationData) { this.leftCoord = locationData.leftCoord this.topCoord = locationData.topCoord } }) }, methods: { saveCoordinates: function (clickEvent) { const coordinates = { leftCoord: clickEvent.layerX, topCoord: clickEvent.layerY } locationRef.set(coordinates) } } } </script>
关键知识点说明
- Firebase数据是异步获取的,组件
mounted钩子执行时,数据大概率还没返回,所以不能直接在mounted里赋值this.location的属性。 - Vuefire会自动帮你把Firebase的引用转换成响应式数据,当数据更新时,组件会自动重新渲染。
- 用
v-if="location"可以避免在数据未加载时渲染依赖数据的元素,防止出现undefined错误。
内容的提问来源于stack exchange,提问作者h.and.h
相关产品推荐
相关产品推荐

