Vue3+Firebase9 Firestore更新商品文档时数据无法编辑问题
问题排查与修复
你的商品编辑功能失效是代码中存在多处逻辑错误导致,逐个修复即可:
editProduct方法逻辑缺失:既没有把待编辑的商品数据填充到v-model绑定的表单对象中,updateDoc调用也缺少必填的更新字段参数,根本没有执行实际的更新操作- Firestore API调用错误:模块化SDK的
doc()方法第一个参数需要传入Firestore实例,而非你定义的collection引用,原有删除、更新操作的文档引用创建方式均不符合API规范 - 快照监听逻辑有bug:每次集合数据变动触发
onSnapshot回调时,你直接往products数组追加数据,会导致列表重复渲染相同商品 - 事件绑定冲突:保存按钮绑定了两个
@click事件,异步的写入操作还没执行就会先关闭弹窗,且现有saveData方法没有区分新增/编辑场景,永远只会执行新增文档逻辑 - 缺少编辑状态标记:代码中没有变量记录当前是新增还是编辑模式,提交时无法判断该调用新增接口还是更新接口
第一步:修正main.js导出
需要把Firestore实例也导出,供组件创建文档引用使用:
// main.js import { initializeApp } from "firebase/app"; import { getFirestore, collection } from "firebase/firestore"; // 替换为你自己的Firebase配置 const firebaseConfig = {}; const app = initializeApp(firebaseConfig); const db = getFirestore(app); const dataBase = collection(db, "products"); // 新增导出db实例 export { db, dataBase };
第二步:修正组件模板
调整列表编辑按钮的传参,移除保存按钮上重复的click绑定:
<template> <!-- 商品列表区域,给编辑按钮传入当前商品数据 --> <div v-for="item in products" :key="item.id" class="product-item"> <p>{{ item.name }} | {{ item.brand }} | {{ item.price }}₴</p> <button @click="editProduct(item)">编辑</button> <button @click="deleteProduct(item.id)">删除</button> </div> <!-- 编辑/新增弹窗 --> <div v-if="toggle" class="modal"> <input type="text" v-model="product.name" placeholder="Назва товару"> <input type="number" v-model="product.price" placeholder="Ціна"> <input type="text" v-model="product.brand" placeholder="Бренд"> <input type="text" v-model="product.category" placeholder="Категорія"> <button class="productbutton" @click="saveData">Save</button> <button class="productbutton" @click="closeModal">Close</button> </div> </template>
第三步:修正组件脚本逻辑
补全编辑状态、修正各方法的API调用、修复快照监听的重复数据问题:
<script> import { db, dataBase } from '../main'; import { addDoc, deleteDoc, onSnapshot, updateDoc, doc } from "firebase/firestore"; import { ref } from 'vue'; export default { name: "Products", setup() { const toggle = ref(false); // 记录当前编辑的商品ID,值为null时是新增模式 const editingId = ref(null); return { toggle, editingId }; }, props: { msg: String }, data() { return { products: [], product: { name: '', price: '', brand: '', category: '' } } }, methods: { // 公共方法:关闭弹窗、重置表单、清空编辑状态 closeModal() { this.toggle = false; this.editingId = null; this.product = { name: '', price: '', brand: '', category: '' }; }, async saveData() { try { if (this.editingId) { // 编辑场景:更新对应ID的文档 const productRef = doc(db, "products", this.editingId); await updateDoc(productRef, this.product); } else { // 新增场景:添加新文档 await addDoc(dataBase, this.product); } // 数据库操作完成后再关闭弹窗 this.closeModal(); } catch (e) { console.error("商品保存失败: ", e); } }, async deleteProduct(id) { if (confirm('Видалити ?')) { // 修正doc方法的传参 await deleteDoc(doc(db, "products", id)); } }, // 点击编辑按钮时触发:填充表单、记录编辑ID、打开弹窗 editProduct(item) { this.editingId = item.id; this.product = { name: item.name, price: item.price, brand: item.brand, category: item.category }; this.toggle = true; } }, created() { onSnapshot(dataBase, (snapshot) => { // 每次快照返回全量数据,先清空本地数组避免重复 this.products = []; snapshot.docs.forEach((doc) => { this.products.push({ ...doc.data(), id: doc.id }) }) }); } }; </script>
内容的提问来源于stack exchange,提问作者VolodymyrPTK
相关产品推荐
相关产品推荐

