最近在写一个根据输入的规格,属性值动态生成sku表格,实现的效果大致如图,这是在vue项目里,结合element-UI表格写的,写好了就整理了一下,把代码贴上来,方便以后使用,不过代码里还是有一些重复的东西没整理,因为急着完成功能,也没太注意代码整洁,以后有时间再整理一下
读取规格列表的功能是,如果你这次存了一个表格给后台,查看详情时,后台返回给你,你需要把它渲染到页面上用的,我这里写的比较复杂,因为用v-model绑定input,取值的时候要用对象取法,所以存进去的时候也是用的对象存放
如果你只是要实现动态生成规格表的话,有这段代码就行了,可以生成3*2*2的组合
/**
* 递归生成规格列表
* @param {*} skuarr 存储每一种排列组合的数组
* @param {*} i 要用list数据的第几项作为基数,i为几,最后的结果就是以list[i]的数据开头,一般以第一项的值放在组合的第一位,如果要以其他属性开头,方法需要变动一下,有兴趣可以自己研究
* @param {*} list 要生成排列的原始数据
*/
var arr = []
function func(skuarr=[], i, list){
for (let j=0; j<list[i].length; j++) { if (i<list.length-1) { // 演示一下第一次执行函数的结果 skuarr[i] = list[i][j] // skuarr[0] = ['黑色'] i=0, j=0 func(skuarr, i+1, list) // 执行递归 skuarr[1] = ['s'] i=1, j=0 } else {
// 拓展运算符合并数组 arr.push([...skuarr,list[i][j]]) // arr[0] = ['黑色','s','好'] i=2不符合if条件,执行else j=0 } } return arr }
const list = [
['黑色','红色','白色'],
['S','M'],
['好','差']
]
console.log(func([],0,list))
// 打印的结果
最近用数组的reduce方法时,想到了另一种实现笛卡尔积的方法,补充进来
handleData () { // 测试的数据 let arrs = [['红','黄', '蓝'], ['大', '中', '小']] // 如果你的数据类型是其他形式,需要转换成二维数组的格式再进行 /** * 思路: 以第一项为基础,循环合并之后的每一项再循环的值 * @param {*} acc 累计的值 * @param {*} cur 当前遍历项 * @param {*} index 当前遍历索引 */ let result = arrs.reduce((acc, cur, index) => { // 从第二项开始合并值 if (index > 0) { let saveArr = [] acc.forEach(item => { cur.forEach(subItem => { saveArr.push(`${item},${subItem}`) }) }) acc = saveArr } return acc }, arrs[0]) // 把数组的第一项传入作为初始值 console.log(result) //["红,大", "红,中", "红,小", "黄,大", "黄,中", "黄,小", "蓝,大", "蓝,中", "蓝,小"] }
整个页面的代码,写得比较乱,见谅
<template> <div> <div class="stand"> <ul> <li class="attr" v-for="(item,index) in standData" :key="index"> <span @click="remove(index)">删除:</span> <el-input class="title" v-model="item.title" placeholder="请输入属性">:</el-input> <div class="putt" v-if="item.attrs.length" v-for="(subitem,i) in item.attrs" :key="i"> <el-input v-model="subitem.attr" placeholder="请输入值"></el-input> <div class="close" @click="closeAtrr(index,i)">×</div> </div> <div class="append" @click="addAtrr(index)">+</div> </li> </ul> <div class="add"> <el-button type="primary" @click="addStand">添加规格</el-button> <el-button type="primary" @click="getTable">生成规格列表</el-button> <el-button type="primary" @click="read">读取规格列表</el-button> </div> </div> <div class="table"> <el-table v-if="isTable" :data="tableData" border style=" 100%"> <el-table-column prop="date" label="属性" width="180"> </el-table-column> <el-table-column prop="name" label="价格1" width="180"> </el-table-column> <el-table-column prop="address" label="价格2"> </el-table-column> </el-table> </div> </div> </template> <style> .table,.stand { padding: 40px; } .table { height: 500px; } .add { margin-top: 20px; } .attr { margin-bottom: 10px; } .el-input { auto; } .putt { display: inline-block; position: relative; margin-right: 10px; } .append { 40px; height: 40px; background-color: aqua; line-height: 40px; text-align: center; display: inline-block; font-size: 28px; cursor: pointer; vertical-align: middle; } .title { background-color: bisque; margin-right: 10px; } .close { position: absolute; 15px; height: 15px; background-color: burlywood; border-radius: 50%; line-height: 15px; text-align: center; right: -5px; top: -5px; } </style> <script> export default { data() { return { tableData: [], input: '', isTable: false, standData: [], list: [], group: [] } }, created() { }, methods: { // 添加规格行 addStand (i) { // 限制规格种类不超过4种 if (this.standData.length>3) { this.$message('不能超过四行') } else { this.standData.push({title: '', attrs: []}) } }, // 添加规格表格 getTable () { this.isTable = true this.tableData = [] this.group = [] this.list = [] // console.log(this.standData); const num = this.standData.length this.standData.forEach(item => { this.list.push(item.attrs) }); // console.log(this.list); var arr = [] var that = this function func(skuarr=[], i){ for (let j=0; j<that.list[i].length; j++) { if (i<that.list.length-1) { skuarr[i] = that.list[i][j].attr func(skuarr, i+1) } else { arr.push([...skuarr,that.list[i][j].attr]) } } return arr } let newList = func([], 0) let b newList.forEach(item => { b = '' for (let i = 0; i < num; i++) { let a = this.standData[i].title a = a + ':' + item[i] b = b + a + ';' } this.group.push(b) }) console.log(this.group) let table = [] for (let j = 0; j < this.group.length; j++) { table.push({ date: this.group[j], name: '', address: '' }) } this.tableData = table }, // 删除规格行 remove (i) { this.standData.splice(i,1) }, // 添加属性值 addAtrr (i) { // 限制属性值不超过5个 if (this.standData[i].attrs.length>4) { this.$message('不能超过5个') } else {
// 存的时候是存的对象 this.standData[i].attrs.push({attr: ''}) } }, // 删除属性值 closeAtrr (a, b) { // console.log(a, b); this.standData[a].attrs.splice(b,1) }, // 读取规格属性数组 read () {
// 如果后台返回的数据是这样的 const arr = [ '颜色:红色;尺码:M;品质:好;', '颜色:红色;尺码:S;品质:好;', '颜色:白色;尺码:M;品质:好;', '颜色:白色;尺码:S;品质:好;' ] const a = arr[0].split(';') const num =a.length-1 let ss = [] for (let tt = 0; tt < num; tt++){ ss.push([]) } arr.forEach(item => { for (let tt = 0; tt < num; tt++){ ss[tt].push(item.split(';')[tt].split(':')[1]) } }) ss = ss.map(item => { return Array.from(new Set(item)) }) for (let s = 0; s < ss.length; s++) { for (let t = 0; t < ss[s].length; t++) { ss[s][t] = {attr:ss[s][t]} } } for (let i = 0; i < num; i++) { this.standData.push({'title': a[i].split(':')[0],attrs: ss[i]}) } console.log(this.standData); } } } </script>