使用Javascript和Firestore填充KDS订单卡片时的内容错位问题
问题:所有订单项都集中显示在第一个订单卡片中
我正在开发基于Javascript和Firestore的KDS厨房显示系统,用卡片展示订单,但所有订单项都被塞进了第一个订单卡片里。
每个订单是Firestore中的一个文档,每个订单下有一个名为Order Items的子集合,专门用来存储该订单的订单项。
我的代码:
const openOrdersQuery = query ( collection(db, "Orders"), where("orderStatus", "==", "New"), orderBy("timeStamp") ); const querySnapshot = onSnapshot(openOrdersQuery, (querySnapshot) => { container.innerHTML = ""; ordersArray = []; querySnapshot.forEach((doc) => { const orderObject = doc.data(); ordersArray.push ( [ orderObject.orderNumber, orderObject.guestRmNum, orderObject.server, orderObject.orderStatus, orderObject.server, orderObject.table, orderObject.timeStamp, orderObject.dateCreated.toDate().toLocaleTimeString() ] ); createOrderCard(orderObject); }); async function createOrderCard(order) { const card = document.createElement('div'); card.classList = 'card-body'; const orderContent = ` <div class="card"> <h1 id="orderNumberH1">Order: ${order.orderNumber}</h1> <h2 id="orderInfoH2">Room: ${order.guestRmNum}</h1> <h2 id="orderInfoH2">Table: ${order.table}</h2> <h2 id="orderInfoH2">Server: ${order.server}</h2> <h2 id="orderInfoH2">Time: ${order.dateCreated.toDate().toLocaleTimeString()}</h2> <hr></hr> <ul id="orderItemsList"></ul> <hr></hr> <button id="completeBtn" onclick="markCompleted('${order.orderNumber}')">Mark As Completed</button> </div> ` ; container.innerHTML += orderContent; var orderItemsArray = new Array(); const orderItemsDocSnap = await getDocs(collection(db, "Orders/" + order.orderNumber + "/Order Items")); orderItemsDocSnap.forEach((doc) => { const orderItemsObject = doc.data(); orderItemsArray.push ( [ orderItemsObject.item, orderItemsObject.quantity, orderItemsObject.modifiers, orderItemsObject.guestRequests ] ); let orderItemsList = document.getElementById("orderItemsList"); let li = document.createElement('li'); li.innerText = orderItemsObject.quantity + "x " + orderItemsObject.item; orderItemsList.appendChild(li); }); } });
问题原因:
所有订单卡片里的列表都用了同一个ID orderItemsList,document.getElementById只会返回页面中第一个匹配该ID的元素,所以不管哪个订单的订单项,都会被加到第一个卡片的列表里。
另外还有两个小问题:
- 多个
h2用了同一个IDorderInfoH2,ID在页面中必须唯一,会导致后续DOM操作出错 createOrderCard是异步函数,在forEach里直接调用会导致卡片创建顺序混乱,可能出现订单项和卡片不匹配的情况
修复后的代码:
const openOrdersQuery = query( collection(db, "Orders"), where("orderStatus", "==", "New"), orderBy("timeStamp") ); const querySnapshot = onSnapshot(openOrdersQuery, async (querySnapshot) => { container.innerHTML = ""; ordersArray = []; // 用for...of循环确保异步操作按顺序执行 for (const doc of querySnapshot.docs) { const orderObject = doc.data(); ordersArray.push([ orderObject.orderNumber, orderObject.guestRmNum, orderObject.server, orderObject.orderStatus, orderObject.server, orderObject.table, orderObject.timeStamp, orderObject.dateCreated.toDate().toLocaleTimeString() ]); await createOrderCard(orderObject); } async function createOrderCard(order) { // 给每个订单的列表生成唯一ID const uniqueListId = `orderItemsList-${order.orderNumber}`; const orderContent = ` <div class="card"> <h1 class="orderNumberH1">Order: ${order.orderNumber}</h1> <h2 class="orderInfoH2">Room: ${order.guestRmNum}</h2> <h2 class="orderInfoH2">Table: ${order.table}</h2> <h2 class="orderInfoH2">Server: ${order.server}</h2> <h2 class="orderInfoH2">Time: ${order.dateCreated.toDate().toLocaleTimeString()}</h2> <hr> <ul id="${uniqueListId}"></ul> <hr> <button class="completeBtn" onclick="markCompleted('${order.orderNumber}')">Mark As Completed</button> </div> `; container.innerHTML += orderContent; // 获取当前订单对应的唯一列表元素 const orderItemsList = document.getElementById(uniqueListId); const orderItemsDocSnap = await getDocs(collection(db, `Orders/${order.orderNumber}/Order Items`)); orderItemsDocSnap.forEach((doc) => { const orderItemsObject = doc.data(); const li = document.createElement('li'); li.innerText = `${orderItemsObject.quantity}x ${orderItemsObject.item}`; orderItemsList.appendChild(li); }); } });
优化说明:
- 用订单号拼接生成唯一的列表ID,确保每个订单的订单项都加到自己的列表里
- 把重复的ID改成class,符合HTML规范
- 用
for...of循环替代forEach,确保异步的订单项查询按订单顺序执行 - 简化了Firestore路径的拼接,用模板字符串更清晰
- 去掉了没用的
orderItemsArray数组(如果后续不需要用可以删掉)
内容的提问来源于stack exchange,提问作者BOSS
相关产品推荐
相关产品推荐

