最近在寫一個根據輸入的規格,屬性值動態生成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="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>
