如何按SKU分组批量渲染商品价格列表
处理商品价格列表时,先按SKU分组,再遍历分组生成结构化HTML,确保每个SKU只显示一次标题,其下列出所有价格选项。通过哈希表分组、模板字符串拼接、一次性DOM插入,避免重复渲染和性能问题,同时做好数据校验与安全编码。
如何按 SKU 分组并批量渲染商品价格列表

先说结论:处理这类聚合展示问题时,核心思路其实很简单——先分组,再遍历。这样就能把相同 SKU 的商品价格信息归拢到一起,避免重复渲染和逻辑混乱,最终输出结构清晰、语义正确的 HTML。
在实际开发中,数据源经常是“扁平”的——同一个 SKU 下可能存在多条记录,分别对应不同的规格(比如按“件”卖多少钱、按“箱”卖多少钱)。如果直接用单层 for 循环逐条追加 HTML,结果就是同一个商品标题被反复输出,这显然不符合“每个 SKU 只显示一次标题,其下列出所有价格选项”的业务需求。
下面是与直接可运行的实现方案,从数据分组到 HTML 输出,一步不落。
步骤一:按 SKU 分组数据
怎么分?经典做法是用一个空对象作哈希表,以 sku 为键,把同 SKU 的所有条目收集到一个数组里:
const groupedData = {};
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
if (!groupedData[item.sku]) {
groupedData[item.sku] = [];
}
groupedData[item.sku].push(item);
}
需要留意的是,这里用 const 和 let 替代了老式的 var,这不仅是现代 JavaScript 的推荐实践,也能避免变量提升带来的潜在问题。
步骤二:遍历分组,构建结构化 HTML
分组完成后,接下来就是渲染输出了。对每个 SKU 分组,只取第一个条目的 sku 和 title 生成标题行,然后遍历该组内所有条目,逐条拼接价格行:
for (const sku in groupedData) {
if (Object.prototype.hasOwnProperty.call(groupedData, sku)) {
const products = groupedData[sku];
const { sku: s, title } = products[0]; // 解构赋值,干净利落
let html = `${s} - ${title}
`;
for (let j = 0; j < products.length; j++) {
const { per, price } = products[j];
html += `${per} — ${parseFloat(price).toFixed(2)}
`;
}
$('#div_1').append(html);
}
}
这里有几个优化点值得强调:
- 使用
Object.prototype.hasOwnProperty.call()替代直接调用,可以更健壮地规避原型链污染风险,属于安全编码的好习惯; - 对价格做了
parseFloat().toFixed(2)格式化,确保货币显示规范,比如1.5会显示为1.50; - 标题
包裹,既提升了语义可访问性,也方便后续样式控制; - 模板字符串的引入,让代码可读性和维护性都有了质的提升,告别了老式的
+拼接。
注意事项
技术上不难,但有些细节还是值得多提两句:
- 不要频繁操作 DOM。 在循环里反复调用
$("#div_1").append()是性能的大敌。推荐的做法是先拼接好完整的 HTML 字符串,最后一次性插入——本例正是如此。如果追求极致性能,也可以考虑用DocumentFragment进一步优化。 - jQuery 版本兼容性。 示例基于 jQuery 3.7.1,如果项目已经迁移到原生 JavaScript,可以替换为
document.getElementById('div_1').insertAdjacentHTML('beforeend', html),效果一样。 - 数据校验不能省。 生产环境最好加上
arr.length和products.[0]的空值判断,防止因数据异常而报错。
这套方案逻辑清晰、扩展性强。后续如果需要支持按 per 排序、折叠展开、或者添加“起订量”等字段,在分组后处理起来都非常方便。可以说,这是处理同类聚合渲染场景的一个标准范式。
