JavaScript如何选择多个section创建订单对象字面量
问题原因
querySelectorAll()返回的是类数组结构的NodeList节点集合,不是单个DOM元素,集合本身没有querySelectorAll、innerText这类元素专属的方法和属性,直接对集合调用元素方法必然报“xxx不是函数”的错误。- 就算对NodeList调用
querySelectorAll,拿到的依然是子节点的集合,集合本身不存在innerText属性,强行读取只能拿到null。 - 你之前通过按钮
parentNode选中单个商品区块的逻辑本身没问题,如果要一次性获取所有商品的订单信息,必须遍历所有.merch区块逐个提取字段,不能直接对集合做操作。
修正后的实现代码
原有HTML结构不需要调整,JS逻辑参考如下,已经包含数量加减、全量订单提取、sessionStorage存储能力:
// 初始化订单存储,优先读取sessionStorage里的已有订单,没有则初始化为空数组 let allOrders = JSON.parse(sessionStorage.getItem('merchOrders')) || []; // 绑定商品数量加减按钮逻辑 document.querySelectorAll('[data-minusOrder], [data-plusOrder]').forEach(btn => { btn.addEventListener('click', function() { const quantityEl = this.parentElement.querySelector('.orderQuantity'); let currentNum = parseInt(quantityEl.innerText); // 减号操作不允许数量小于0 if (this.hasAttribute('data-minusOrder')) { currentNum = Math.max(0, currentNum - 1); } else { currentNum += 1; } quantityEl.innerText = currentNum; }) }) // 绑定下单按钮事件 const orderButtons = document.querySelectorAll(".orderButton"); orderButtons.forEach(function(button) { button.addEventListener("click", function() { // 单商品加购场景:获取当前点击按钮所属的商品区块,比parentNode容错率更高 const currentMerch = this.closest('.merch'); const currentItem = { id: currentMerch.id, title: currentMerch.querySelector(".title").innerText.trim(), price: currentMerch.querySelector(".price").innerText.trim(), description: currentMerch.querySelector(".description").innerText.trim(), quantity: parseInt(currentMerch.querySelector(".orderQuantity").innerText) }; if (currentItem.quantity === 0) { alert('请先选择商品数量'); return; } // 全量订单场景:遍历所有商品区块,提取所有选购数量大于0的商品 const allMerchList = document.querySelectorAll('.merch'); const validOrderList = Array.from(allMerchList).map(merchEl => { return { id: merchEl.id, title: merchEl.querySelector(".title").innerText.trim(), price: merchEl.querySelector(".price").innerText.trim(), description: merchEl.querySelector(".description").innerText.trim(), quantity: parseInt(merchEl.querySelector(".orderQuantity").innerText) } }).filter(item => item.quantity > 0); // 存入sessionStorage,后续提交服务端直接读取该字段即可 sessionStorage.setItem('merchOrders', JSON.stringify(validOrderList)); console.log('当前有效订单:', validOrderList); }); });
关键注意点
- 找单个匹配元素用
querySelector(),找一组匹配元素才用querySelectorAll();拿到NodeList集合后必须遍历内部元素,才能执行DOM属性读取、方法调用操作,不要直接对集合调用元素方法。 - 查找按钮所属的商品区块推荐用
this.closest('.merch'),比多层写parentNode容错率高,后续就算调整DOM结构、在按钮外层套容器,也不会找错父级区块。 - 注意:sessionStorage只能存储字符串类型数据,存对象、数组类型的订单数据时,必须先用
JSON.stringify()转成字符串,读取时再用JSON.parse()转回JS对象,否则会存成"[object Object]"的无效数据。 - 读取元素文本后建议加
.trim()去掉首尾多余的空格、换行,避免存储的字段带无用格式。 - 商品数量读取到的是字符串类型,存数据前要转成Number类型,避免后续计算总价时出现字符串拼接的低级错误。
内容的提问来源于stack exchange,提问作者Daniel L
相关产品推荐
相关产品推荐

