如何从Firebase获取指定新增元素并避免重复渲染?
Firebase新增数据仅渲染本次新增项实现方案
问题根源
现有逻辑直接遍历快照返回的全量文档,每次触发监听都把所有银行数据重新追加到页面DOM中,必然导致历史数据重复绘制。Firebase onSnapshot 监听本身提供了变更文档查询能力,不需要每次处理全量数据。
调整步骤
- 放弃遍历
snapshot.docs全量文档的写法,改用快照自带的docChanges()方法,仅筛选变更类型为added的文档处理 - 增加初始加载标记,区分首次页面加载时拉取的历史数据、和后续操作产生的新增数据
- 把原全量批量渲染的方法改为单条数据插入方法,避免累加innerHTML时重复拼接已有内容
- 修正原代码中贷款相关字段映射错位的问题
- 调整成功弹窗触发时机,确保数据真正写入数据库后再弹出提示
调整后完整代码
// 初始加载标记:用于区分首次拉取的历史数据和后续新增数据 let isInitialLoad = true; // 提交银行数据 async function sendBankData() { await db.collection("banks").add({ bankName: bankName.value, interestRate: interestRate.value, maximumLoan: maximumLoan.value, minimumDownPayment: minimumDownPayment.value, loanTerm: loanTerm.value, }); // 注意:成功提示不要写在这里,异步写入可能失败,放到监听回调里触发更准确 } // 监听银行数据 function getBanks() { db.collection("banks").onSnapshot((snapshot) => { const docChanges = snapshot.docChanges(); docChanges.forEach(change => { // 只处理新增类型的文档,修改、删除类型可后续自行扩展逻辑 if (change.type === 'added') { const bankItem = { id: change.doc.id, ...change.doc.data() }; // 插入单条银行项到页面 renderSingleBank(bankItem); // 非初始加载状态下收到新增文档,即为本次提交的新数据,触发成功提示 if (!isInitialLoad) successfulPopUp(); } }); // 首次加载的所有历史数据处理完成后,关闭初始加载标记 if (isInitialLoad) isInitialLoad = false; }); } // 渲染单条银行数据,替代原全量遍历渲染的generateBanks方法 function renderSingleBank(bank) { const bankDom = ` <div class="bank-item" data-bank-id="${bank.id}"> <img src="./img/edit-icon1.png" alt="编辑"> <div class="bank-text"> Bank name: <span class="bank-name">${bank.bankName}</span> </div> <div class="bank-text"> Interest rate: <span class="bank-interest-rate">${bank.interestRate}</span> </div> <div class="bank-text"> Maximum loan: <span class="bank-maximum-loan">${bank.maximumLoan}</span> </div> <div class="bank-text"> Minimum down payment: <span class="bank-minimum-down-payment">${bank.minimumDownPayment}</span> </div> <div class="bank-text"> Loan term: <span class="bank-loan-term">${bank.loanTerm}</span> </div> </div> `; bankItems.insertAdjacentHTML('beforeend', bankDom); }
逻辑说明
docChanges()会返回本次快照和上一次快照相比的差异文档列表,不会返回无变动的历史数据,从根源上避免重复处理已渲染内容- 首次绑定监听时,返回的所有
added类型变更都是数据库中已存在的历史数据,一次性渲染完成后将isInitialLoad设为false,后续再收到added变更即为用户新提交的银行数据,仅对这部分数据做渲染和提示 - 使用
insertAdjacentHTML做DOM插入,比直接累加innerHTML性能更高,也不会触发已有DOM的重新解析 - 每个银行项增加
data-bank-id属性存储文档ID,后续实现编辑、删除功能时可直接通过ID快速定位对应DOM - 修正了原代码中三个业务字段错位的问题:原代码将最高可贷金额、最低首付、贷款期限三个字段的取值写反,调整后字段和展示位置一一对应
内容的提问来源于stack exchange,提问作者userName
相关产品推荐
相关产品推荐

