1、数据结构 (后台提供的)
goodsBaseInfo: {
// 单个商品
goodsId: "",
"skuNameList":[
// 最多三个,最少一个;
{//规格名称
"id":"3333",//id
"name":"颜色",//名字
//"specificationName": [
//{"value":"白色"},
//{"value":"黑色"},
//{"value":"灰灰色"},
//]
},
],
"skuList":[
{//规格名称
"id":"123456",//id
"specification": '[{"id":"3333", "value":"白色"},{"id":"4444","value":"XL"},{"id":"5555","value":"河南"}]', // 规格内容
"price":"120",//价格
"stock":"10"//库存
},
],
},
data 中定义
modelTypeLists: [], // 规格类型列表
selectArr: [], //存放被选中的值
shopItemInfo: {}, //存放要和选中的值进行匹配的数据
subIndex: [], //是否选中 因为不确定是多规格还是单规格,所以这里定义数组来判断
2、首先需要将数据格式进行转换,(规格名称拼接为对应的键)
rewriteDataFormat() {
// 从后台拿到数据之后,进行数据处理
let that = this;
// 将规格名称格式转换为键值对;
let { skuNameList, resDataSkuList } = that.data;
// let skuNameList = skuNameList;
// let resDataSkuList = resDataSkuList;
let skuList = [];
let shopItemInfo = {}
resDataSkuList.map((item, index) => {
item['specification'] = JSON.parse(item.specification);
let itemKey = '';
item['specification'].map((i, i_j) => {
i['isShow'] = true;
// 属性名拼接
itemKey = itemKey + ',' + i.value;
// console.log('itemKey:', itemKey);
})
// 去掉属性名拼接中第一个逗号
let reg = new RegExp(",","");
let a = itemKey.replace(reg,"");
// console.log('itemKey reg:', a);
shopItemInfo[a] = item;
skuList.push(item);
});
console.log('skuList:', skuList);
console.log('shopItemInfo:', shopItemInfo);
that.setData({ shopItemInfo});
console.log('skuNameList:', skuNameList);
// 组装,规格名称
skuNameList.map((it, indx) => {
var specificationName = [];
skuList.map((ite, ind) => {
ite.specification.map((j, ind_j) => {
if (it.id === j.id) {
let valueName = j.value;
specificationName.push(valueName);
}
})
});
// 去重
specificationName = [...new Set(specificationName)];
let newSpecificationNameArr = []
specificationName.map((item, index) =>{
let a = {'value': item};
newSpecificationNameArr.push(a);
})
it['specificationName'] = newSpecificationNameArr;
});
console.log('skuNameList:', skuNameList);
that.setData({
modelTypeLists: skuNameList,
// baseSkuNameList: skuNameList,
})
},
其中:shopItemInfo很重要:
得到如:
shopItemInfo: {
"灰色,NL,南京":{
id: "29f9ca54e3b442608194cdad00a7b9ca",
price: 6,
specification: [
{id: "bafc8e356361449c85dfc44bbe7204f0", value: "灰色", isShow: true},
{id: "00eecd2b3bc946afb5a7bfb7d5a510f4", value: "NL", isShow: true},
{id: "a4cbb3513e884e99ac3dcbb0c8fcc622", value: "南京", isShow: true}],
stock: 99
},
"灰色,NL,东郡":{
id: "29f9ca54e3b442608194cdad00a7b9ca",
price: 6,
specification: [
{id: "bafc8e356361449c85dfc44bbe7204f0", value: "灰色", isShow: true},
{id: "00eecd2b3bc946afb5a7bfb7d5a510f4", value: "NL", isShow: true},
{id: "a4cbb3513e884e99ac3dcbb0c8fcc622", value: "东郡", isShow: true}],
stock: 99
}
}
得到skuNameList
如下:
skuNameList:[
{
id: "bafc8e356361449c85dfc44bbe7204f0",
name: "颜色",
specificationName: [
{value: "灰色"},
{value: "白色"}
]
},
{
id: "bafc8e356361449c85dfc44bbe7204f0",
name: "产地",
specificationName: [
{value: "南京"},
{value: "东郡"}
]
},
{
id: "bafc8e356361449c85dfc44bbe7204f0",
name: "尺寸",
specificationName: [
{value: "ML"},
{value: "XL"}
]
}
]
3、小程序DOM结构
<view class="pop_lists">
<view class="sku_item" wx:for="{{modelTypeLists}}" wx:key="id" wx:for-index="idx" wx:for-item="i">
<view class="pop_lists_name">{{i.name}}</view>
<view class="pop_item">
<view wx:for="{{i.specificationName}}" wx:for-index="idxj" wx:for-item="j" wx:key="_idxj" data-value="{{j.value}}" data-index="{{idxj}}" data-parent-index="{{idx}}" bindtap="chouseModelType" class="pop_li {{subIndex[idx] === idxj ? 'cur_chouse' : ''}}{{j.isShow ? 'disabled': ''}}">
{{j.value}}
</view>
</view>
</view>
</view>
4、chooseModelType事件处理
chooseModelType(event) {
let that = this;
console.log('event:', event)
let eventData = event.currentTarget.dataset;
let value = eventData.value;
let curIndex = eventData.index;
let curIndexParent = eventData.parentIndex;
let {selectArr, subIndex} = that.data;
if (selectArr[curIndexParent] != value) {
selectArr[curIndexParent] = value;
subIndex[curIndexParent] = curIndex;
} else {
selectArr[curIndexParent] = "";
subIndex[curIndexParent] = -1; //去掉选中的颜色
}
console.log('selectArr:', selectArr);
console.log('subIndex:', subIndex);
that.setData({
selectArr,
subIndex
})
that.checkItem()
},
判断选中的规格中是否有对应的库存量
checkItem: function () {
var that = this;
let {selectArr, subIndex, modelTypeLists, shopItemInfo} = that.data;
var option = modelTypeLists;
var result = []; //定义数组储存被选中的值
for(var i in option){
result[i] = selectArr[i] ? selectArr[i] : '';
}
for (var i in option) {
var last = result[i]; //把选中的值存放到字符串last去
// 关键处理
for (var k in option[i].specificationName) {
result[i] = option[i].specificationName[k].value; //赋值,存在直接覆盖,不存在往里面添加name值
option[i].specificationName[k]['isShow'] = that.isStocks(result); //在数据里面添加字段isShow来判断是否可以选择
}
result[i] = last; //还原,目的是记录点下去那个值,避免下一次执行循环时被覆盖
}
// 更新数据
that.setData({
modelTypeLists:option
})
// 匹配到对应的规格信息
if (shopItemInfo[result]) {
that.setData({
modelTypePrice: shopItemInfo[result].price || '0',
modelTypeStock: shopItemInfo[result].stock,
modelTypeName: result,
})
// 存储规格名
shopItemInfo[result]['modelTypeName'] = result;
that.setData({
modelType: shopItemInfo[result]
})
}
},
isStocks: function (result) {
// 关键所在 判断是否可以选择规格
let that = this;
let { shopItemInfo } = that.data;
for (var i in result) {
if (result[i] == '') {
return false; //如果数组里有为空的值,那直接返回true
}
}
return shopItemInfo[result].stock == 0 ? true : false //匹配选中的数据的库存,若不为空返回true反之返回false
},
关键是自己组装数据,根据对象的键(key)值,匹配到对应的value;
效果如下图:
欢迎优化批评;
1、明确后台提供的数据结构;
2、优化重组数据,以适合前端使用;
3、根据逐一并且是按顺序保存选中的规格名称;
4、根据选中的规格名称匹配对应规格的库存量,若库存量0,则对应的规格是无法选择的,以及价格;
5、更多项目可以查看 github地址;若找不到为私密项目,可以加QQ:982701105
劳动不易感谢鼓励