技术栈: 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>