该篇文章是我通过查阅资料和自己思考实践后完整的写出最后效果的,先看最终的效果。
商品多规格SKU的效果
一、前提说明
1、思维能力:想要自己完整的写出来首先需要有基本的逻辑思维,最核心的有两条,一是多规格数学理论上是怎么计算的,就是乘积的结果数。二是数据的比较。
2、本次我开发的环境非常的简单,就是VUE2的一个页面,纯JS实现的,如果对JS不熟悉,估计很难看懂。
3、关于商品规格的乘积的算法我推荐你去看这篇文章。如果看的吃力,烧脑,那就多看几篇。直到你真的看明白了,那就举一反三,融会贯通。该文简单的给解释清楚了原理和实现的思路,我代码里面的规格的核心算法也是按照这个思路来的。
二、实施步骤
1、首先对规格的基础数据的设置(这里很简单),就一个属性名称,然后属性名称下面可以自己定义多个规格,比如 颜色:红色,绿色,蓝色。尺寸:大,中,小。这是基本的数据,比如:你有两个规格,且每个规格有3种属性,那么总的规格的种类数就是3x3=9种。
最原始的系统的规格列表(这里可以是后端给的)
2、所以只要选择了一种属性的一个规格值,则开始有规格数据生成了。这里你需要抽象出你想要的组合的数据的结构是什么样的,因为这一步操作是简单,但是跟你下一步使用笛卡尔积算具体有哪些规格的数据结果是有直接关系的。每一步都是环环相扣的。通过选择属性和名称和规格,我这里要的组合数据结构是这样的。
前端用户选择规格名称和规格值后我想组装的数据结构
guigedata.valuelist = [
{
name:"颜色",
value:[
{
name:"绿色",
img:""
},
{
name:"蓝色",
img:""
}
]
},{
name:"尺寸",
value:[
{
name:"大",
img:""
},
{
name:"中",
img:""
},
{
name:"小",
img:""
}
]
}
];
组装上面数据的方法
guigenewArradd(name,itemobj){
let fatherisnew = true
let sonisnew = true
let indexs = null
this.guigedata.guigenewArr.map((item,key)=>{
if(item.name == name){
fatherisnew = false
indexs = key
//检查
item.value.map(item2=>{
if(item2.name == itemobj.name){
sonisnew = false
}
})
}
});
if(fatherisnew){
let pushtem = {
name:name,
value:[itemobj]
};
this.guigedata.guigenewArr.push(pushtem);
}
if(sonisnew&&!fatherisnew){
this.guigedata.guigenewArr[indexs].value.push(itemobj)
}
},
3、通过上一步组合的数据,利用笛卡尔积算法获得最终可以获得的规格组合(这是核心,实现这一步获得到了,才能进行数据的组装和判断)。方法如下
//所有的组合往products里面生成了
allguigeaddtoproducts(allguige){
let that = this
allguige.map((item,key)=>{
let products_basemodel ={...that.products_basemodel}
products_basemodel.guigevalue = item
this.allguigeaddtoproductsact( that.formDialog.products,products_basemodel);
})
},
allguigeaddtoproductsact( prosuctsobj,products_basemodel){
//这里首选的一个基本思路是 要么修改现在的数据,要么增加数据
// prosuctsobj.push(products_basemodel)
if(prosuctsobj.length == 0 ||(prosuctsobj.length>0 && prosuctsobj[0].guigevalue.length == 0)){
prosuctsobj[0].guigevalue=products_basemodel.guigevalue
}else{
//存在有规格的数据了
// 首先判断是变更还是增加
//1、变更的情况,原本存在规格,只是新的在原来的基础上,多了一个规格而已。这就是变更
// let addnew = true;
let real_quanju_chongfu = false
let add_or_edit = null
let edit_index = null
prosuctsobj.map((item,index)=>{
if(item.guigevalue.length == products_basemodel.guigevalue.length && item.guigevalue.length>0){
//console.log("从这里走")
// add_or_edit = "add"
//如果长度一样,那么就看值有没有重复的,如果最后没得重复的,那就最后增加
let tem_all_result = [];
for (let i = 0;i<products_basemodel.guigevalue.length;i++) {
let newObj = products_basemodel.guigevalue[i]
let tem_result = item.guigevalue.some((obj) => obj.name === newObj.name && obj.value === newObj.value);
tem_all_result.push(tem_result);
}
let alltrue = tem_all_result.every((value) => value === true)
if(tem_all_result.length > 0 && alltrue ){
//那就证明真的重复了
real_quanju_chongfu = true
}
}
//第一步只是数量上是否一致
if((item.guigevalue.length + 1) == products_basemodel.guigevalue.length){
//要要变更的数据
//这里就是选 老数据完全在新数据里面存在的
let tem_all_result = [];
for(let i=0;i<item.guigevalue.length;i++){
let newObj = item.guigevalue[i]
let tem_result = products_basemodel.guigevalue.some((obj) => obj.name === newObj.name && obj.value === newObj.value);
tem_all_result.push(tem_result)
}
let alltrue = tem_all_result.every((value) => value === true)
if(tem_all_result.length > 0 && alltrue ){
//找到这个家伙了,他全都是重复的
add_or_edit = "edit"
edit_index = index
}
}
})
//全局重复啥也不用管
if(real_quanju_chongfu){
//pass
}else{
//检查是不是需要更新 不需要就增加
if(add_or_edit == 'edit' && edit_index != null){
//那就更新吧
prosuctsobj[edit_index].guigevalue = products_basemodel.guigevalue
}else{
//那就增加新的
prosuctsobj.push(products_basemodel)
}
}
}
},
4、把获得的组合往最终的产品属性规格数组中添加数据,这一步看起来简单,实际是需要计算,有点复杂,但是简单一句话就是:你需要判断你上一步获得的规格到底是应该在原本的规格上进行修改,还是增加一个新的之前数据里没有存在的规格。举例,比如你之前选择了大中小三种规格,但是当你再增加一个颜色,比如红色,这时候其实还是只有三种规格,因为你只加了一个颜色进去,所以理论上你的规格组合就是[大,红色],[中,红色],[小,红色],用户有可能之前已经设置了大的库存是100,那么你增加新的规格进去的时候,就只能是往规格里面增加一个颜色的属性,值是红色,而不能直接覆盖掉原本的所有数据。所以这里的就需要对每一个数据进行循环的遍历。我这里实现的思路是,拿每一个新组合的规格,去循环遍历已经存在的规格,每一个都去进行比较。但是这里的比较其实只有三种结果,一是我的新的规格在我原本的产品属性规格中已经存在不需要任何的处理。二是,我原本的某一个产品规格属性他所有的值在我新的规格中已经存在且属性总量+1的话等于当前的我组合的规格数量,这样我就判断是需要增加了。三是,既不是一和二的,那就是需要新增规格的。这里的思维有点复杂,我写代码之前我都觉得我没有想明白,我是写的过程中,才不断的想明白的。核心就是我判断一个新的规格在我老的数据里面,到底应该是修改,还是新增,还是啥也不干(判断重复)。我最开始也是不知道到底应该怎么写逻辑判断,写着写着就想明白了(这也印证了一个道理,很多事情,你不去做,光坐着想,全都是问题,只有去做了,才能找到出路,不做光想是不行的,只要想通了七八成,就去干)。