预览
DEMO和使用方法
DEMO:https://guosugaz.gitee.io/kun-vue-sku/
github: https://github.com/Guosugaz/kun-vue-sku
码云:https://gitee.com/guosugaz/kun-vue-sku
实现思路
说明使用的数据
const info = [
{
id: 1,price: 99,store: 9, 颜色:"粉色,https://inews.gtimg.com/newsapp_ls/0/12169344339_295195/0",尺码: "小",内存: "4g",
},
{
id: 2,price: 99,store: 9,颜色: "粉色",尺码: "小",内存: "8g",
},
{
id: 3,price: 33,store: 99,颜色: "粉色",尺码: "大",内存: "4g",
},
{
id: 4,price: 99,store: 9,颜色: "黄色",尺码: "小",内存: "4g",
},
{
id: 5,price: 14,store: 99,颜色: "蓝色",尺码: "大",内存: "8g",
}
]
const showInfo = {
"颜色": [
{ "disable": false, "active": false, "value": "粉色", "img": "https://inews.gtimg.com/newsapp_ls/0/12169344339_295195/0" },
{ "disable": false, "active": false, "value": "黄色" },
{ "disable": false, "active": false, "value": "蓝色" }
],
"尺码": [
{ "disable": false, "active": false, "value": "小" },
{ "disable": false, "active": false, "value": "大" }
],
"内存": [
{ "disable": false, "active": false, "value": "4g" },
{ "disable": false, "active": false, "value": "8g" }
]
}
const showInfoKeys = Object.keys(showInfo);
const select = {}; // {颜色: '粉色'}
const selectKeys = []; // 已选择的规格
1.首先获取各个sku和未完全选择的库存
// 未完全选择的sku库存
let skuPartNameStock = {};
// 完全的sku库存
let skuStock = {};
// 处理后端数据为展示数据时拼接完整的sku库存和id
function getInfo() {
// 处理数据 实现详情github库 /src/lib/Spec.vue getInfo函数
....
// 插入完成的sku 库存和id
skuStock[valueArr.join("-")] = `${item[storeKey]},${item.id}`;
}
/*
* 核心算法,获取已选择sku的库存数
* @param {Array} selected 已选择的sku数组 ["粉丝", "L"]
*/
function getRemainByKey(selected = []) {
const selectedJoin = selected.join("-");
// 如果已有缓存则返回
if (typeof skuPartNameStock[selectedJoin] !== "undefined") {
return skuPartNameStock[selectedJoin];
}
// 所有sku已选择 及时缓存
if (selected.length === showInfoKeys.length) {
skuPartNameStock[selectedJoin] = skuStock[selectedJoin]
? Number(skuStock[selectedJoin].split(",")[0])
: 0;
return skuPartNameStock[selectedJoin];
}
let remainStock = 0;
const willSelected = [];
for (let i = 0; i < showInfoKeys.length; i += 1) {
let thatArr = showInfo[showInfoKeys[i]];
// 对应规格的sku是否已选择
const exist = thatArr.find(
({ value }) => value === selected[0]
);
if (exist && selected.length > 0) {
willSelected.push(selected.shift());
} else {
// 对应sku未选择,则遍历该规格所有sku
for (let j = 0; j < thatArr.length; j += 1) {
remainStock += getRemainByKey(
willSelected.concat(thatArr[j].value, selected)
);
}
break;
}
}
// 返回前缓存
skuPartNameStock[selectedJoin] = remainStock;
return skuPartNameStock[selectedJoin];
}
处理后的数据
// skuPartNameStock
{
"粉色-小-4g":9,
"粉色-小-8g":9,
"粉色-小":18,
"粉色-大-4g":99,
"粉色-大-8g":0,
"粉色-大":99,
"粉色":117,
"黄色-小-4g":9,
"黄色-小-8g":0,
"黄色-小":9,
"黄色-大-4g":0,
"黄色-大-8g":0,
"黄色-大":0,
"黄色":9,
"蓝色-小-4g":0,
"蓝色-小-8g":0,
"蓝色-小":0,
"蓝色-大-4g":0,
"蓝色-大-8g":99,
"蓝色-大":99,
"蓝色":99,"":225,
"粉色-4g":108,
"粉色-8g":9
}
// skuStock
{
"粉色-小-4g":"9,1",
"粉色-小-8g":"9,2",
"粉色-大-4g":"99,3",
"黄色-小-4g":"9,4",
"蓝色-大-8g":"99,5"
}
2.更新状态
// 获取 selectKeys
fucntion getSelectKeys() {
let arr = [];
showInfoKeys.forEach((key, index) => {
arr[index] = select[key] ? select[key] : "";
});
selectKeys = arr;
}
// 更新状态
fucntion fetchStatus() {
// 根据已选择的sku来筛选库存
showInfoKeys.forEach((key, skuIdx) => {
let sku = showInfo[key];
const curSelected = selectKeys.slice();
// 已选的不用更新
sku.forEach((skuInfo) => {
// 已选择规格的跳过
if (skuInfo.active) return;
// 将不同sku代入计算库存
const cacheKey = curSelected[skuIdx];
// 组合没选中的值和已选中的值
curSelected[skuIdx] = skuInfo.value;
// 获取不同组合的库存
const stock = getRemainByKey(
curSelected.filter((item) => item)
);
curSelected[skuIdx] = cacheKey;
// 更新sku状态
skuInfo.disable = stock <= 0;
});
});
}
参考
https://www.cnblogs.com/formercoding/p/12995715.html
https://quincychen.cn/sku_algorithm/
后记
推荐自己根据项目的需求改写该组件,组件存放位置 /src/lib/Spec.vue