Vue+Element plus realizes product specification practice (sku list)

Require: 

  1. initial state

 

        2. Click the "Add Specification" button to add a set of specification content

        3. Click the "x" button to delete the specification content

         4. Click the "Add specification value" button to add a set of specification value content

        5. Click the "x" button to delete the content of the specification value

         6. Click the "Refresh" button to combine the above specifications to get the table data

         7. Add up to 3 sets of specification content

        8. Specific code

<template>
  <div class="textlist">
    <div class="textlist-data">
      <div class="textlist-but">
        <el-button @click="addCreata" style="background-color: #f56643;color: white;" :icon="Plus">添加按钮</el-button>
      </div>
      <div>
        <template v-for="itemd in listdata.value">
          <div class="textlist-data-list">
            <el-input v-model="itemd[0].name" placeholder="请输入规格名称" style="width: 80%;margin: 20px;" />
            <span class="textlist-add" @click="addvalue(itemd)">添加规格值</span>
            <span class="textlist-span" @click="close(itemd)"></span>
          </div>
          <div class="textlist-data-list">
            <template v-for="items in itemd[0].valued">
              <div class="textlist-content">
                <span class="icon" @click="delele(itemd, items)"></span>
                <el-input v-model="items.value" placeholder="请输入规格值" style="margin: 20px;"></el-input>
              </div>
            </template>
          </div>
        </template>
      </div>
      <div>
        <el-button @click="renovate" style="background-color: #f56643;color: white;" :icon="Refresh">刷新</el-button>
        <el-table :data="tableData[0]" style="width: 100%" border>
          <template v-for="(item, index) in tableData[0]">
            <el-table-column :prop="'sku_' + item.title[index]" :label="tableData[0][0].title[index]"
              v-if="tableData[0][0].title[index]">
            </el-table-column>
          </template>
          <el-table-column prop="num" label="销售价"></el-table-column>
        </el-table>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { Plus, Refresh } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus';
import { ref, reactive } from "vue"
let listdata = reactive({
  value: [] as any[],
  specificationList: [] as any[],
})
let tableData: any = ref([])
const addCreata = () => {//用于初始化,第一遍数据
  listdata.value.push([{ name: '', valued: [{ value: '' }] }])
}
//点击添加规格值
function addvalue(itemd: any) {
  if (itemd[0].valued.length > 2) {//判断如果数组长度大于二的话
    return ElMessage.warning('注意喔!最多上传三次规格');
  }
  itemd[0].valued.push({ value: '' })
}
//规格属性内容点击关闭叉号按钮
function close(items: any) {
  const index = listdata.value.findIndex(item => item == items)
  listdata.value.splice(index, 1)//根据当前所点击的规格属性截取
}
//规格属性点击关闭叉号按钮
function delele(listvalue: any, listitem: any) {
  const index = listdata.value.findIndex(item => item == listvalue)//查找当前属性名
  const indexs = listdata.value[index][0].valued.findIndex((item: any) => listitem == item)
  listdata.value[index][0].valued.splice(indexs, 1)
}
//刷新
function renovate() {
  Object.assign(listdata.specificationList, listdata.value)//对象浅度拷贝(表格内容)
  const specList = listdata.specificationList//用于生成2维数组
  const valueList = specList.filter((item: any) => item.length).map(ele => {
    let arr = [] as any[]
    ele[0].valued.forEach((a: { value: string }) => {
      arr.push(a.value)
    })
    return arr
  })
  const titlesList = specList.filter((item: any) => item.length).map((item: any) => item[0].name)//获取维度名称,放到数组中
  var skuArr = valueList.reduce((pre: string[][], item: any[]) => {// 使用笛卡尔积算法将数据进行交叉处理
    var array: string[][] = []//用这个空数组去匹配交叉数组
    pre.forEach(item1 => {//拿出空的一维数组
      item.forEach(item2 => {//遍历标签名称内容,也就是交叉匹配
        array.push(item1.concat([item2]))//连接起来添加进array空数组
        return array
      })
    })
    return array
  }, [[]])
  let list = skuArr.map((item: any, index: number) => {//构建表格--最终渲染出表格
    let obj = { //对象将属性值并渲染到表格中
      num: 0,
      title: titlesList
    } as any
    item.forEach((val: number, index: number) => {// 遍历循环添加到sku数组中
      obj['sku_' + titlesList[index]] = val;// 相当于是添加一个对象属性
      obj['data'] = item.join(',')
    });
    return obj;
  })
  tableData.value.length = 0;//每次删除输入框调用笛卡尔算法
  tableData.value.push(list)//最终添加到表格总
}
</script>
<style scoped>
.textlist {
  width: 100%;
  background-color: #f0f2f5;
}

.textlist-data {
  width: 90%;
  background-color: #fff;
  margin: auto;
}
.textlist-add{
  font-size: 14px;color: #f56643;cursor: pointer;
}
.textlist-but {
  margin: 10px 0 0;
}

.textlist-data-list {
  position: relative;
}

.textlist-content {
  position: relative;
  display: inline-block;

}
.textlist-span::before {
  content: 'x';
  position: absolute;
  right: 20px;
  top: 4px;
  font-size: 14px;
  color: #f56643;
  cursor: pointer;
}

.icon::before {
  content: 'x';
  position: absolute;
  right: -20px;
  top: 6px;
  font-size: 20px;
  color: #f56643;
  cursor: pointer;
  z-index: 999;
}

</style>

 

        9. The overall effect:

 

Guess you like

Origin blog.csdn.net/m0_71933813/article/details/130304889
Recommended