js实现spu
实现SPU(标准化产品单元)的JavaScript方法
SPU(Standard Product Unit)是电商系统中用于描述标准化产品的概念,通常与SKU(Stock Keeping Unit)配合使用。以下是几种常见的实现方式:
基础数据结构设计
使用对象或类来表示SPU和SKU的关系:
class SPU {
constructor(id, name, description, attributes) {
this.id = id;
this.name = name;
this.description = description;
this.attributes = attributes; // 通用属性如品牌、类别
this.skus = []; // 关联的SKU列表
}
addSKU(sku) {
this.skus.push(sku);
}
}
class SKU {
constructor(id, spuId, price, stock, specs) {
this.id = id;
this.spuId = spuId; // 关联的SPU ID
this.price = price;
this.stock = stock;
this.specs = specs; // 具体规格如颜色、尺寸
}
}
属性组合生成SKU
根据SPU的通用属性和可变属性生成所有可能的SKU组合:

function generateSKUs(spu, variantAttributes) {
const combinations = cartesianProduct(variantAttributes);
return combinations.map((combo, index) => {
return new SKU(
`${spu.id}-${index}`,
spu.id,
spu.basePrice,
spu.baseStock,
combo
);
});
}
function cartesianProduct(arr) {
return arr.reduce((a, b) =>
a.flatMap(x => b.map(y => [...x, y])),
[[]]
);
}
前端展示处理
在商品详情页展示SPU和SKU选择器:
function renderSPU(spu) {
const specGroups = groupSpecs(spu.skus);
// 渲染规格选择器
specGroups.forEach(group => {
const selector = createSelector(group.name, group.values);
document.getElementById('specs').appendChild(selector);
});
}
function groupSpecs(skus) {
const specMap = new Map();
skus.forEach(sku => {
Object.entries(sku.specs).forEach(([name, value]) => {
if (!specMap.has(name)) {
specMap.set(name, new Set());
}
specMap.get(name).add(value);
});
});
return Array.from(specMap).map(([name, values]) => ({
name,
values: Array.from(values)
}));
}
状态管理
使用状态管理库(如Vuex或Redux)处理SPU-SKU选择逻辑:

// Redux示例
const spuReducer = (state = {}, action) => {
switch (action.type) {
case 'SELECT_SPEC':
const newSelections = {
...state.specSelections,
[action.specName]: action.specValue
};
const availableSKUs = filterSKUs(state.spu.skus, newSelections);
return {
...state,
specSelections: newSelections,
availableSKUs
};
default:
return state;
}
};
function filterSKUs(skus, selections) {
return skus.filter(sku =>
Object.entries(selections).every(([key, value]) =>
sku.specs[key] === value
)
);
}
与后端API交互
典型的前后端交互模式:
async function fetchSPU(spuId) {
const response = await fetch(`/api/spus/${spuId}`);
const spuData = await response.json();
const spu = new SPU(
spuData.id,
spuData.name,
spuData.description,
spuData.attributes
);
spuData.skus.forEach(skuData => {
spu.addSKU(new SKU(
skuData.id,
spuData.id,
skuData.price,
skuData.stock,
skuData.specs
));
});
return spu;
}
性能优化建议
对于大型商品目录的优化处理:
// 使用Map缓存SPU数据
const spuCache = new Map();
async function getSPU(spuId) {
if (spuCache.has(spuId)) {
return spuCache.get(spuId);
}
const spu = await fetchSPU(spuId);
spuCache.set(spuId, spu);
return spu;
}
// 虚拟滚动处理大量SKU
function renderVirtualList(skus, container, itemHeight) {
const visibleCount = Math.ceil(container.clientHeight / itemHeight);
let startIndex = 0;
function updateVisibleItems() {
const endIndex = startIndex + visibleCount;
const visibleItems = skus.slice(startIndex, endIndex);
// 更新DOM...
}
container.addEventListener('scroll', () => {
startIndex = Math.floor(container.scrollTop / itemHeight);
updateVisibleItems();
});
}
这些实现方式可以根据具体业务需求进行调整,核心思想是将不变的商品信息(SPU)与可变的规格信息(SKU)分离管理。






