VUE3+Element Plus/Ant Design Vue实现动态表格(动态生成表头,表头可配置)

技术栈: Vue3+TypeScript+Pinia+Element Plus、Ant Design Vue

因调研需求,此项目根据Pinia数据状态存储、mock接口请求数据

简介

常规的项目基架,安装并引入TypeScript、Pinia、Element Plus、Ant Design Vue,配置好后进行实际编码。
主要分为三个部分:全量表头数据(表头项数组)、已选表头数据(十进制数字)、页面渲染。
流程:从Pinia中获取已经选中的数据,转化为二进制数字,每一位对应一个表头项的显示/隐藏,根据全量表头位进行匹配处理,获得实际勾选展示的表头项数组,进而根据UI框架的要求处理成对应的结构。
初始化时:
初始化时
配置列时:
在这里插入图片描述

Options 可选表头项配置

config.js

// // 选项数据
export const options = [
  { label: 'Label1', value: 'label1' },
  { label: 'Label2', value: 'label2' },
  { label: 'Label3', value: 'label3' },
  { label: 'Label4', value: 'label4' },
  { label: 'Label5', value: 'label5' },
  { label: 'Label6', value: 'label6' },
  { label: 'Label7', value: 'label7' },
  { label: 'Label8', value: 'label8' },
  { label: 'Label9', value: 'label9' },
  { label: 'Label10', value: 'label10' },
  { label: 'Label11', value: 'label11' }
]

pinia selected 已选中表头存储

import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useSelectedStore = defineStore('selected', () => {
  const selected = ref(0)
  
  // 修改
  function setSelected(value: number) {
    selected.value = value
    console.log('setSelected', selected.value)
  }
// 获取
  function getSelected() {
    return selected.value
  }
  return { selected, setSelected, getSelected }
})

转换工具

utils.js

import { options } from "@/config/index"

// 十进制转二进制字符串,自动补位(第一个为第一位)
export const numberToHex = (num: number, length?: number) => {
  let str = num.toString(2);
  if (!length) return str;
  let len = str.length;
  while (len < length) {
    str = '0' + str;
    len++;
  }
  return str;
}

// 二进制字符串转十进制数字
export const hex2Number = (hex: string) => {
  return parseInt(hex, 2);
}

// 十进制数根据全量列表转化成label数字
export const numberToLabels = (num: number) => {
  console.log('numberToLabels 输入',num);
  const targetArr: Array<any> = []
  const originArr = numberToHex(num, options.length).split('').reverse();
  originArr.forEach((item, index) => {
    if (item !== '0') targetArr.push(options[index].value);
  })
  console.log('numberToLabels 输出',targetArr);
  return targetArr;
}

// labels数字转十进制数字
export const labelsToNumber = (opt: Array<string>) => {
  console.log('labelsToNumber 输入',opt);
  let resHex = ''
  options.forEach((item: { label: String, value: String, }) => resHex = ((opt.find((checked) => checked === item.value)) ? '1' : '0') + resHex)
  console.log('labelsToNumber 输出',hex2Number(resHex));
  return hex2Number(resHex);
}

模拟接口请求数据列表

api.js


export const getData = () => {
  const total = 8;
  const colums = 11;
  const data:Array<any> = [];
  for(let i=0; i<total; i++) {
    const obj = {};
    for(let j = 0; j<colums; j++) {
      obj[`label${j+1}`] = String(Math.random());
    }
    data.push(obj);
  }
  return new Promise((resolve,reject) => resolve({
    code: 200,
    msg: 'success',
    data: data
  }))
}

配置表头项

setting.vue

<template>
  <div>
    <el-checkbox-group v-model="checkList">
      <el-checkbox v-for="opt in options" :key="opt" :label="opt.value">
        {{ opt.label }}
      </el-checkbox>
    </el-checkbox-group>
    <el-button type="primary" @click="handleConfirm">Confirm</el-button>
    <el-button @click="handleCancel">Cancel</el-button>
  </div>
</template>

<script setup lang='ts'>
import { ref } from "vue";
import { ElMessage } from 'element-plus'
import { numberToLabels, labelsToNumber } from '@/utils/index'
import { useSelectedStore } from "@/stores/selected"
import { options } from "@/config/index"

/** 处理存储的数据 */
const { selected, setSelected } = useSelectedStore();
console.log('selected', selected)
const targetArr = numberToLabels(selected)
const checkList = ref([...targetArr])

// 提交修改
const handleConfirm = () => {
  let resNum = labelsToNumber(checkList.value)
  ElMessage({
    message: `配置成功,值: ${resNum}`,
    type: 'success',
  })
  setSelected(resNum);
}

// 重制
const handleCancel = () => {
  checkList.value = [...targetArr]
}
</script>

<style lang='scss' scoped></style>

界面展示

element plus

<template>
  <div>
    <h1>ElementPlus</h1>
    <el-table :data="tableData" style="width: 100%">
      <el-table-column v-for="col in columns" :key="col.prop" :prop="col.prop" :label="col.label" />
    </el-table>
  </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue'
import { getData } from '@/api/index'
import { useSelectedStore } from "@/stores/selected"
import { numberToLabels } from '@/utils/index'
import { options } from "@/config/index"



const { selected } = useSelectedStore();

const tableData = ref();
// 表格数据初始化
const getInitData = () => {
  getData().then(res => {
    tableData.value = res.data;
  })
}
getInitData();

// 列配置
const columnsProps = numberToLabels(selected);
const columns = []
options.forEach((item: { label: String, value: String, }) => {
  if (columnsProps.indexOf(item.value) !== -1) columns.push({ prop: item.value, label: item.label })
})

</script>

ant design

<template>
  <div>
    <h1>AntDesign</h1>
    <a-table :dataSource="tableData" :columns="columns" />
  </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue'
import { getData } from '@/api/index'
import { useSelectedStore } from "@/stores/selected"
import { numberToLabels } from '@/utils/index'
import { options } from "@/config/index"

const { selected } = useSelectedStore();
// 表格数据初始化
const tableData = ref();
const getInitData = () => {
  getData().then(res => {
    tableData.value = res.data;
  })
}
getInitData();

// 列配置
const columnsProps = numberToLabels(selected);
const columns = []
options.forEach((item: { label: String, value: String, }) => {
  if (columnsProps.indexOf(item.value) !== -1) columns.push({ dataIndex: item.value, key: item.value, title: item.label })
})

</script>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值