先看看sku的多规格选择演示。
我们需要的是再后台上传库存规格和所属规格来进行判断,需要再不同属性间来回切换。
全幼儿园最聪明我在这借鉴全幼儿园最聪明sku的算法并加以更改,以自己的理解来记录一下。
我的理解是先创建一个空白的矩阵,x轴和y轴是各个规格按顺序排列。
initEmptyAdjMatrix() {
this.productSpecValueVo.forEach((prop) => {
prop.mainImgSpecsVOS.forEach((attr) => {
this.list.push(attr.specsValueName)
attr.isActive = false
attr.isDisabled = false
})
})
for (let i = 0; i < this.list.length; i++) {
this.listindex[i] = new Array(this.list.length).fill(0);
}
console.log(this.listindex);
}
我在其中还绑定了相应的状态维护字段,用来判断状态,这是其结果表格:
红色 | 绿色 | 11寸 | 12寸 | 13寸 | |
红色 | 0 | 0 | 0 | 0 | 0 |
绿色 | 0 | 0 | 0 | 0 | 0 |
11寸 | 0 | 0 | 0 | 0 | 0 |
12寸 | 0 | 0 | 0 | 0 | 0 |
13寸 | 0 | 0 | 0 | 0 | 0 |
在此基础上,比如红色,11寸,我会将其id填入对应的表格,以下是我排列的函数和结果:
以下是具体方法:
// 将规格属性组中的属性在无向图中联系起来
associateAttributes(attributes, skuId) {
attributes.forEach((attr1) => {
attributes.forEach((attr2) => {
// 因 spec 与 sku 数据结构不一致,需作处理
if (attr1 !== attr2 || attr1.specsValueName !== attr2.specsValueName) {
if (attr1.specsValueName && attr2.specsValueName) {
attr1 = attr1.specsValueName;
attr2 = attr2.specsValueName;
}
//对三个以上的规格进行处理
const value1 = attr1.specsValueName ? attr1.specsValueName : attr1;
const value2 = attr2.specsValueName ? attr2.specsValueName : attr2;
const index1 = this.list.indexOf(value1);
const index2 = this.list.indexOf(value2);
if (index1 > -1 && index2 > -1) {
if (this.listindex[index1][index2]) {
this.listindex[index1][index2].add(skuId);
} else {
this.listindex[index1][index2] = new Set([skuId]);
}
}
}
});
});
},
setAdjMatrixValue() {
this.productSkuVOS.forEach((sku) => {
this.associateAttributes(sku.skuAttribute, sku.skuId);
});
this.productSpecValueVo.forEach((prop) => {
this.associateAttributes(prop.mainImgSpecsVOS, '99');
});
},
数据填入后我们需要将点击的逻辑写入:
// 触发函数,传入规格类下标和规格下标
choose(propertyIndex, attributeIndex) {
const attr = this.productSpecValueVo[propertyIndex].mainImgSpecsVOS[attributeIndex]
// 重置每个规格的 isActive 状态
const isActive = !attr.isActive;
this.productSpecValueVo[propertyIndex].mainImgSpecsVOS[attributeIndex].isActive =
isActive;
if (isActive) {
this.productSpecValueVo[propertyIndex].mainImgSpecsVOS.forEach((attr, index) => {
if (index !== attributeIndex) {
attr.isActive = false;
}
});
}
// 维护当前已选的规格列表
this.selected = [];
this.productSpecValueVo.forEach((prop) => {
prop.mainImgSpecsVOS.forEach((attr) => {
if (attr.isActive) {
this.selected.push(attr.specsValueName);
}
});
});
// 重置每个规格的禁用状态
this.productSpecValueVo.forEach((prop) => {
prop.mainImgSpecsVOS.forEach((attr) => {
attr.isDisabled = !this.canAttributeSelect(attr);
});
});
//判断选择是否是主键并更新图片
this.productSpecValueVo[0].mainImgSpecsVOS.map((item1, index1) => {
if (Object.is(item1.specsValueName, this.selected[0])) {
this.default_data = item1
}
})
//判断是否选择完全
if (this.selected.length == this.productSpecValueVo.length) {
this.productSkuVOS.map((item, index) => {
if (JSON.stringify(item.skuAttribute) === JSON.stringify(this.selected)) {
this.selected_id = item.skuId
this.judge = false
this.tiptitle = this.shopCarJudge ? '添加购物车' : '下单'
this.price = item.price
}
})
} else {
this.judge = true
this.tiptitle = '请选择规格'
}
},
canAttributeSelect(attribute) {
//判断选择情况
if (!this.selected || !this.selected.length || attribute.isActive) {
return true;
}
let res = [];
this.selected.forEach((value) => {
const index1 = this.list.indexOf(value);
const index2 = this.list.indexOf(attribute.specsValueName);
res.push(this.listindex[index1][index2]);
});
if (res.some((item) => (item === 0))) {
return false;
} else if (res.some((item) => (item.has('99')))) {
return true;
} else {
const first = res[0];
const others = res.slice(1);
return Array.from(first).some((skuId) => (others.every((item) => (item.has(skuId)))));
}
},