Vue+Pinia+Firebase Firestore:避免多ID查询数据被覆盖
解决方案
要实现不同patientid的支付数据不被覆盖,你需要调整Mainpayments的数据结构,并修改getPayments方法中的赋值逻辑,同时处理Firestore实时监听的重复订阅问题。
方案1:使用对象存储(推荐,查找高效)
将Mainpayments改为键值对结构,key为patientid,value为对应支付数据数组,这样可以直接通过patientid快速定位并更新数据。
修改代码:
- 调整state中的结构:
state: () => { return { loadingPayments: false, payments: [], Mainpayments: {}, // 改为对象,键是patientid,值是支付数组 transition: '', dayPayments: [], selectedDate: today(), paymentSubscriptions: {} // 存储每个patientid的监听取消函数,避免重复订阅 } },
- 更新
getPayments方法:
async getPayments(id) { // 若已监听该patientid,先取消之前的监听 if (this.paymentSubscriptions[id]) { this.paymentSubscriptions[id]() } paymentsCollectionQuery = query(paymentsCollectionRef, where("patientid", "==", id), orderBy("date", "desc")) this.loadingPayments = true // 保存新的监听取消函数 this.paymentSubscriptions[id] = onSnapshot(paymentsCollectionQuery, (querySnapshot) => { const payments = [] querySnapshot.forEach((doc) => { let payment = { id: doc.data().id, details: doc.data().details, date: doc.data().date, currencyhavetopay: doc.data().currencyhavetopay, currencypaid: doc.data().currencypaid, moneyhavetopay: doc.data().moneyhavetopay, moneypaid: doc.data().moneypaid, tooth: doc.data().tooth, doctor: doc.data().doctor, patientid: doc.data().patientid, } payments.push(payment) }) // 直接赋值,存在则更新,不存在则新增 this.Mainpayments[id] = payments this.loadingPayments = false }, error => { console.log('error', error.message) this.loadingPayments = false }) },
方案2:使用数组存储(保持顺序,适合遍历场景)
如果需要保持patientid的查询顺序,可以将Mainpayments改为数组,每个元素包含patientid和对应的payments数组。
修改代码:
- 调整state中的结构:
state: () => { return { loadingPayments: false, payments: [], Mainpayments: [], // 结构:[{ patientid: 'xxx', payments: [...] }, ...] transition: '', dayPayments: [], selectedDate: today(), paymentSubscriptions: {} // 存储监听取消函数 } },
- 更新
getPayments方法:
async getPayments(id) { // 取消已有监听 if (this.paymentSubscriptions[id]) { this.paymentSubscriptions[id]() } paymentsCollectionQuery = query(paymentsCollectionRef, where("patientid", "==", id), orderBy("date", "desc")) this.loadingPayments = true this.paymentSubscriptions[id] = onSnapshot(paymentsCollectionQuery, (querySnapshot) => { const payments = [] querySnapshot.forEach((doc) => { let payment = { id: doc.data().id, details: doc.data().details, date: doc.data().date, currencyhavetopay: doc.data().currencyhavetopay, currencypaid: doc.data().currencypaid, moneyhavetopay: doc.data().moneyhavetopay, moneypaid: doc.data().moneypaid, tooth: doc.data().tooth, doctor: doc.data().doctor, patientid: doc.data().patientid, } payments.push(payment) }) // 查找是否已有该patientid的条目 const existingIndex = this.Mainpayments.findIndex(item => item.patientid === id) if (existingIndex !== -1) { // 更新已有条目 this.Mainpayments[existingIndex].payments = payments } else { // 添加新条目 this.Mainpayments.push({ patientid: id, payments }) } this.loadingPayments = false }, error => { console.log('error', error.message) this.loadingPayments = false }) },
额外注意事项
- 为避免内存泄漏,在组件卸载或不再需要监听时,调用取消监听的方法:
actions: { cancelAllSubscriptions() { Object.values(this.paymentSubscriptions).forEach(unsubscribe => unsubscribe()) this.paymentSubscriptions = {} // 可选:清空Mainpayments // this.Mainpayments = {} 或 [] } }
在组件中:
import { onUnmounted } from 'vue' import { useStorePayments } from '@/stores/storePayments' const storePayments = useStorePayments() onUnmounted(() => { storePayments.cancelAllSubscriptions() })
内容的提问来源于stack exchange,提问作者omar jasim
相关产品推荐
相关产品推荐

