结合element-ui表格自动生成sku规格列表

最近在写一个根据输入的规格,属性值动态生成sku表格,实现的效果大致如图,这是在vue项目里,结合element-UI表格写的,写好了就整理了一下,把代码贴上来,方便以后使用,不过代码里还是有一些重复的东西没整理,因为急着完成功能,也没太注意代码整洁,以后有时间再整理一下

结合element-ui表格自动生成sku规格列表

读取规格列表的功能是,如果你这次存了一个表格给后台,查看详情时,后台返回给你,你需要把它渲染到页面上用的,我这里写的比较复杂,因为用v-model绑定input,取值的时候要用对象取法,所以存进去的时候也是用的对象存放

如果你只是要实现动态生成规格表的话,有这段代码就行了,可以生成3*2*2的组合

/**
* 递归生成规格列表
* @param {*} skuarr 存储每一种排列组合的数组
* @param {*} i 要用list数据的第几项作为基数,i为几,最后的结果就是以list[i]的数据开头,一般以第一项的值放在组合的第一位,如果要以其他属性开头,方法需要变动一下,有兴趣可以自己研究
* @param {*} list 要生成排列的原始数据
*/
var arr = []
function func(skuarr=[], i, list){  
) {  
        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))
// 打印的结果
  1. 0:(3) ["黑色", "S", "好"]
  2. 1:(3) ["黑色", "S", "差"]
  3. 2:(3) ["黑色", "M", "好"]
  4. 3:(3) ["黑色", "M", "差"]
  5. 4:(3) ["红色", "S", "好"]
  6. 5:(3) ["红色", "S", "差"]
  7. 6:(3) ["红色", "M", "好"]
  8. 7:(3) ["红色", "M", "差"]
  9. 8:(3) ["白色", "S", "好"]
  10. 9:(3) ["白色", "S", "差"]
  11. 10:(3) ["白色", "M", "好"]
  12. 11:(3) ["白色", "M", "差"]
 

最近用数组的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>