1.根据笛卡尔积算法来构建二维数组
- 变量1接收过滤的tag标签,生成二维数组组
- 变量2获取维度名称
判断如果规格长度等于0,直接把规格属性赋空,然后使用笛卡尔积算法将数据进行交叉处理(使用reduce方法,参数1:空的二维数组,参数2:变量2的数据(维度名称标签),在声明一个空的数组array(用这个空数组去匹配交叉数组),再拿出reduce参数1空的二维数组,forEach循环遍历,在使用forEach遍历变量2数据(维度名称标签),进行交叉匹配,连接起来添加进array空数组,然后在这个二维数组中重新映射为对象数组,进行拼接数据构建sku表格
// 根据笛卡尔积来构建二维数组,在这个二维数组中重新映射为对象数组,首先过滤
function addTag() {
// 根据笛卡尔积来构建二维数组,在这个二维数组中重新映射为对象数组
const specList = formListAdd.value.specificationList//过滤tag标签,生成2维数组:
//数组对象中的数组取出,得到一个二维数组(蓝色tag标签)
const valueList = specList.filter((item: any) => item.values.length).map((item: any) => item.values)
// 添加name值(黄色tag标签)//获取维度名称,放到数组中 右边
const titlesList = specList.filter((item: any) => item.title.length).map((item: any) => item.title)
if (valueList.length == 0) {//如果规格没有这种属性,直接把规格属性赋空
formListAdd.value.skuList = []
return
}
// 使用笛卡尔积算法将数据进行交叉处理
var skuArr = valueList.reduce((pre: string[][], next: any[]) => {//pre是一个空的二维数组 next(黄色tag标签)的内容也就是类型
var array: string[][] = []//用这个空数组去匹配交叉数组
pre.forEach(item1 => {//拿出空的一维数组
next.forEach(item2 => {//遍历黄色tag标签内容,也就是交叉匹配
array.push(item1.concat([item2]))//连接起来添加进array空数组
return array
})
})
return array
}, [[]])
// 进行拼接数据
//构建sku表格--最终渲染出表格
let list = skuArr.map((item: any, index: number) => {//根据skuArr来构建对象数组
let obj = { //对象将属性值并渲染到sku表格中
price: formListAdd.value.skuList[index] ? formListAdd.value.skuList[index].price : 1,//现价
originalPrice: formListAdd.value.skuList[index] ? formListAdd.value.skuList[index].originalPrice : 1,//原价
vipPrice: formListAdd.value.skuList[index] ? formListAdd.value.skuList[index].vipPrice : 1,//vip价格
stock: 0,//库存
weight: 0,//重量
img: "",//图片
barCode: 0,//随机码
title: '',//维度名称
specification: ''
} as any
// 遍历循环添加到sku数组中
item.forEach((val: number, index: number) => {
// 相当于是添加一个对象
obj['sku_' + titlesList[index]] = val;
obj['title'] = item.join(',')
obj['specification'] += formListAdd.value.specificationList[index].title + '_' + val + ','
});
return obj;
})
formListAdd.value.skuList.length = 0;//每次删除tag标签调用笛卡尔算法
Object.assign(formListAdd.value.skuList, list)//最终合并渲染数据到sku表
}
2.合并表格
首先获取规格列表,判断然后对要跨行的列进行计算排除最后一个树形列,定义跨行的数量为1,循环遍历获取每一列要合并的
行数,将跨行的数量=后面数组长度的乘积,每次跨行的数量相同,所以当前行索引取余数%跨行数量==0就是要跨行的开始
<!-- 商品详情表格渲染 span-method合并行或列的计算方法 -->
<el-table :data="formListAdd.skuList" style="width: 100%" border :span-method="objectSpanMethod">
<el-table-column width="100" align="center"
v-for="item in (<any>formListAdd.specificationList).filter((item: any) => item.values.length > 0)"
:prop="'sku_' + item.title" :label="item.title" />
<!-- 循环数组,过滤数组的长度 -->
<el-table-column prop="SkuIds" label="SkuId" align="center" />
<el-table-column prop="vipPrice" label="¥VIP价(元)" width="150" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.vipPrice" size="small" :min="1" />
</template>
</el-table-column>
<el-table-column prop="originalPrice" label="吊牌价" width="150" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.originalPrice" size="small" :min="1" />
</template>
</el-table-column>
<el-table-column prop="price" label="价格" width="150" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.price" size="small" :min="1" />
</template>
</el-table-column>
<el-table-column prop="stock" label="库存" width="150" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.stock" size="small" :min="1" />
</template>
</el-table-column>
<el-table-column prop="weight" label="重量" width="150" align="center">
<template #default="scope">
<el-input-number v-model="scope.row.weight" size="small" :min="1" />
</template>
</el-table-column>
<el-table-column prop="img" label="SUK图片" width="150" align="center">
<template #default="scope">
<el-upload action="http://192.168.1.188:8080/upload/admin" :show-file-list="false"
:headers="headers" :on-success="handlePicSuccess" :before-upload="beforeAvatarUpload">
<img v-if="scope.row.img" :src="scope.row.img" class="avatars" />
<el-icon v-else @click="imgIndex = scope.$index">
<Upload />
</el-icon>
</el-upload>
</template>
</el-table-column>
<el-table-column prop="barCode" label="条形码" width="250" align="center">
<template #default="scope">
<el-input v-model="scope.row.barCode" size="small" style="width:200px;">
<template #append>
<el-button @click="scope.row.barCode = new Date().getTime()" size="small">随机</el-button>
</template>
</el-input>
</template>
</el-table-column>
</el-table>
const objectSpanMethod = ({ row, column, rowIndex, columnIndex }: any) => {//行 列 行的下标 列的下标
//拿到第一列要合并的行数(获取列表) 第一次渲染页面时弹框数组为空,会报空指针错误,需要使用?.运算符解决
let specList = formListAdd.value.specificationList.filter((e: any) => e.values?.length > 0);
if (columnIndex < specList.length - 1) {//对要跨行的列进行计算,排除最后一个属性列(最后一个属性列不存在跨行中)
let rowSpanNum = 1;//跨行的数量
for (let i = columnIndex + 1; i < specList.length; i++) {
//依次拿到每一列要合并的行数
rowSpanNum *= specList[i].values.length;//跨行的数量=后面数组长度的乘积
}
if (rowIndex % rowSpanNum === 0) {//每次跨行的数量相同,所以当前行索引取余数%跨行数量==0就是要跨行的开始
return { rowspan: rowSpanNum, colspan: 1 } //当条件成立时,即合并行数
} else {
return { rowspan: 0, colspan: 0 }
}
}
注意(实现具体思路)
a.首先我们添加规格时会生成一个规格的表格,然后也会生成一个由tag标签形成的标签项,此项就是添加的规格
b.例如我添加两个规格,一个是尺寸,一个是颜色,那么就会生成两个tag标签项,当然tag标签项除了有规格之外还有一个动态编辑标签,意思就是跨域往规格里面添加不同的规格,如颜色可以添加红色,蓝色,尺寸可以添加XL,M等维度,那么在表格中怎么去生成尺寸和颜色这两个规格的数据呢?
c.首先我是定义一个数组,然后我们添加规格的时候把规格以对象的形式push进去数组中,当我们去编辑tag标签的时候,把tab的内容以数组的方式添加进去规格的对象中,做完这些操作之后就是生成SKU表格了
d.这里是采用计算属性的方式来实现的,首先使用map映射的方式获取到所有的规格组成一个二维数组例如上面添加的尺寸和颜色,那么就会获取到一个二维数组,二维数组中XL,M组成一个数组,蓝色,红色也组成一个数组,然后使用map获取到尺寸和颜色组成的数组
e.接下来是针对于二维数组使用笛卡尔积算法获得所有规格交叉之后组成的二维数组,意思就是获取一个二维数组,二维数组中尺寸和颜色全部交叉组成,组成新的一个二维数组,即生成XL和红色,XL和蓝色,M和红色,M和蓝色的数组,得到新的二维数组之后
f.我们还需要把这个二维数组使用双重循环的方式拿到每个数组的元素,然后以规格当做key,具体的规格值当做value的方式添加进去对象中
g.然后定义一个数组,把对象push进去数组中,最后把这个数组渲染到表格上就可以了,表格中的的prop属性是定义对象时的规格key值
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。