You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue3+Firebase9 Firestore获取文档ID失败、无法删除文档问题

问题根因

两个报错都是Firebase v9异步API使用错误+变量命名冲突导致的,具体问题点:

  • addDoc是异步API,返回Promise对象,没有加await等待操作完成就直接取id,拿到的自然是undefined,同时这种写法下try/catch也无法捕获写入失败的错误
  • deleteProduct方法的形参名和从Firebase导入的doc()引用构造函数重名,运行时会把传入的商品对象当成函数调用,直接报错导致删除失败
  • onSnapshot实时监听回调里直接往products数组push数据,会导致每次数据变更(新增/删除/修改)时重复插入重复条目,列表数据会出现重复渲染问题

修正步骤

1. 确认main.js正确导出集合引用

确保组件能正常拿到集合实例,补充导出逻辑:

// main.js
import { initializeApp } from "firebase/app";
import { getFirestore, collection } from "firebase/firestore";
// 替换为你自己的Firebase项目配置
const firebaseConfig = { /* 你的配置项 */ };
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);
// 导出products集合引用
export const dataBase = collection(db, "products");

2. 修正Products组件代码

核心改动:异步方法加await、修改变量名避免命名冲突、快照触发时重置本地数组避免重复数据:

<script>
import { dataBase } from '../main';
import { addDoc, onSnapshot, doc, deleteDoc } from "firebase/firestore";

export default {
  name: "Products",
  props: {
    msg: String
  },
  data() {
    return {
      products: [],
      product: {
        name: '',
        detail: '',
        price: '',
        brand: '',
        category: ''
      }
    }
  },
  methods: {
    // 异步方法加async标记
    async saveData() {
      try {
        // 等待写入完成拿到实际文档引用
        const docRef = await addDoc(dataBase, this.product);
        console.log("Document written with ID: ", docRef.id);
        this.reset();
      } catch (e) {
        console.error("Error adding document: ", e);
      }
    },
    reset() {
      Object.assign(this.$data, this.$options.data.apply(this));
    },
    // 形参不要命名为doc,避免和导入的doc函数冲突
    async deleteProduct(product) {
      try {
        await deleteDoc(doc(dataBase, product.id));
        console.log("Document deleted successfully");
      } catch (e) {
        console.error("Error deleting document: ", e);
      }
    }
  },
  created() {
    onSnapshot(dataBase, (snapshot) => {
      // 每次快照返回全量数据,先清空原数组避免重复
      this.products = []
      snapshot.docs.forEach((docItem) => {
        this.products.push({ ...docItem.data(), id: docItem.id })
      })
    });
  }
};
</script>

补充说明

  • 所有Firebase返回Promise的操作(addDoc/deleteDoc/updateDoc等)都需要加await或者.then()才能拿到实际返回结果
  • 写代码时注意不要让局部变量/形参名和导入的工具函数重名,这类问题隐蔽性很强,排查成本高
  • Firestore实时监听的快照每次都会返回查询范围内的全量数据,触发回调时一定要先重置本地存储的数组,不然会出现重复数据

内容的提问来源于stack exchange,提问作者VolodymyrPTK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:06:27