最近在寫一個根據輸入的規格,屬性值動態生成sku表格,實現的效果大體如圖,這是在vue項目裏,結合element-UI表格寫的,寫好了就整理了一下,把代碼貼上來,方便之後使用,不過代碼裏仍是有一些重複的東西沒整理,由於急着完成功能,也沒太注意代碼整潔,之後有時間再整理一下vue
讀取規格列表的功能是,若是你此次存了一個表格給後臺,查看詳情時,後臺返回給你,你須要把它渲染到頁面上用的,我這裏寫的比較複雜,由於用v-model綁定input,取值的時候要用對象取法,因此存進去的時候也是用的對象存放數組
若是你只是要實現動態生成規格表的話,有這段代碼就好了,能夠生成3*2*2的組合app
var arr = []
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="width: 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 { width: auto; } .putt { display: inline-block; position: relative; margin-right: 10px; } .append { width: 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; width: 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>