在Vue项目中获取Firebase Firestore子集合数据返回null如何解决?
问题修正方案
1. 基础错误排查
- 函数名不匹配:你导出的可复用查询函数名为
getCollection,组件内调用时写的是getAllComments,如果导入时没有手动重命名,首先要修正调用的函数名。 - 异步逻辑理解偏差:Firestore的
onSnapshot是异步监听逻辑,setup执行时同步打印comments.value,此时监听回调还没触发,ref初始值为null属于正常现象,Vue会在数据更新后自动响应视图,如果你需要在JS逻辑中使用返回的数据,用watch监听comments变化即可。
2. 结果数组为空的修复
你遍历快照文档时加了doc.data().createdAt的判断条件,如果评论入库时没有携带createdAt字段,所有数据都会被过滤导致结果为空,修改遍历逻辑:
snap.docs.forEach(doc => { const data = doc.data() // 保留判断的话要确保入库时带了createdAt字段,建议额外带上文档id方便后续操作 if(data.createdAt) { results.push({...data, id: doc.id}) } })
同时建议把comments的初始值从null改为空数组,减少后续非空判断的冗余代码。
3. 计算属性逻辑修正
comments是存储所有评论的数组,不能直接取comments.value.userId,如果需要判断单条评论的归属权,改成接收评论参数的判断函数:
const isOwner = (comment) => { return !!(user.value && comment.userId === user.value.uid) }
完整修正代码
可复用查询函数
import { ref, watchEffect } from 'vue'; import { projectFirestore } from '../firebase/config'; const getCollection = (collection, id, subcollection) => { const comments = ref([]); const error = ref(null); const collectionRef = projectFirestore .collection(collection) .doc(id) .collection(subcollection); const unsub = collectionRef.onSnapshot( snap => { let results = []; snap.docs.forEach(doc => { const data = doc.data() data.createdAt && results.push({...data, id: doc.id}); }); comments.value = results; error.value = null; }, err => { console.log(err.message); comments.value = []; error.value = 'could not fetch the data'; } ); watchEffect(onInvalidate => { onInvalidate(() => unsub()); }); return { error, comments }; }; export default getCollection;
Comments.vue组件
import { ref, watch } from 'vue' import getCollection from '你的getCollection文件路径' import getUser from '你的getUser文件路径' export default { props: ['id'], setup(props) { const { user } = getUser(); const content = ref(''); const { comments, error } = getCollection('posts', props.id, 'comments'); // 需要在JS中使用评论数据时监听变化 watch(comments, (newComments) => { console.log('获取到的评论数据:', newComments) }, { deep: true }) // 单条评论归属权判断 const isOwner = (comment) => { return !!(user.value && comment.userId === user.value.uid) } // 评论提交逻辑自行实现,注意入库时要带createdAt字段 const handleComment = () => { // 提交评论代码 } return { user, content, handleComment, comments, error, isOwner }; } };
组件模板使用示例
<template> <div v-if="error" class="error">{{ error }}</div> <div v-for="item in comments" :key="item.id"> <p>{{ item.content }}</p> <button v-if="isOwner(item)">删除评论</button> </div> </template>
内容的提问来源于stack exchange,提问作者Uros
相关产品推荐
相关产品推荐

