「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
前言
最近接到一个动态渲染table的需求。感觉也挺有意思的,特此分享给大家。
技术栈是ivewUI
实现思路是key
值与data
值相匹配。
分析需求
- 根据用户选择的条件生成一个动态的
table
,并且table
的列和行都是动态的。 table
数据根据用户选择的日期月份以及其他条件来进行生成。- 最后一行对整列的数据进行统计。
- 统计行的数据点击后可跳转到对应的
echarts
数据页面。
综合上面的需求我们可以知道 这个table
的数据是由用户根据不同的条件查询而生成的,对于前端实现来说,我们应该从后端接口拿到数据进行处理,然后再展示在table
中。
实现过程
由于当前项目使用的UI组件库是iview
,因此我们可以使用iview
中table组件来实现上面所示的需求。
在iview table
组件中: 我们可以传递 columns
和data
这两个参数进行表格的渲染。
<Table :columns="columns" :data="data"></Table>
columns
可以自定义列。 data
则表示需要渲染的数据
由于行和列都是动态的,因此需要和后端沟通好接口数据。
我们可以让后端在接口中分别返回列的渲染数据。以及需要渲染的data
数据。
//假设我们封装了一个请求api
const {data,code} = await api('/queryList',{})
if(code === '200'){
/* 后台返回的数据如下
{
code:200,
data:{
"columnList":[
{time:20220201,week:'周二'},
{time:20220202,week:'周三'}
...,
{time:20220228,week:'周一'}],
"rows": [{
"name": "早上8:30",
"data": {
"20220201": 0,
"20220202": 0,
"20220203": 0,
"20220204": 0,
"20220205": 0,
...,
"20220226": 0,
"20220227": 0,
"20220228": 0
}
}]
}
} */
}
拿到数据后我们就可以进行渲染了:
const list = data?.rows
const col = data?.columnList
//如果返回接口中行的长度大于0说明我们有数据需要渲染
if(list?.length>0){
//由于后台没有返回统计行的数据 因此需要我们自己去计算
//先实现最后一行的统计
let obj ={}
let result = []
list?.map(i =>{
for(const [key,value] of Object.entries(i.data)){
obj[key] = obj[key]? obj[key] + value : 0 + value
}
})
// 计算完最后一行的数据。我们还需要对第一列的显示进行处理
// 给obj加上一个属性让它能渲染到对应的列 给定第一列的key值为tips 给obj加上tips属性
obj.tips = '总人数'
// 此外 为了实现统计栏数据点击可跳转的功能 我们还需要加上一个标识用于统计行的自定义渲染处理
obj.sign = true
// 然后我们给list中的所有数据添加tips这个属性用于绑定首行的key值
result = list?.map(i =>{
return {
//给首列的数据赋值
tips: i.name,
//其他数据不改动
...i.data
}
})
//将统计行的数据push到result数组中
result?.push(obj)
// 处理完 数据之后 我们开始自定表头行
//这时候就需要用到col中的数据了
col.map((i,index) =>{
if(index === 0){
col.push({
title:'班次/日期',
//这个key非常重要 key和data中键匹配才能渲染到数据
key: 'tips',
minWidth: 200,
//设置首列固定
fixed:'left',
align: 'center'
//使用render函数自定义数据的展现 这个根据业务随机发挥哦
render:(h,{row}) => row.tips?.split(',').map(m =>h('div',m))
})
}
//如果index不是0 那么就渲染后台返回的数据
col.push({
title:`${i.time.substring(4)}\t(${(this.weekDay.find(m => m.code ===i.week)).message})`,
minWidth:110,
align:'center',
key:`${i.time}`,
render: (h,params) =>{
let {commercialDistrictCode='',stationId=''} = this.selectQuery
//这里判断是否携带sign标识 如果携带 则表示为统计行的数据 需要进行自定义的渲染
if(params.row.sign){
return h('a', {
on: {
click: async () => {
this.$router.push({
// router-path
path:''
})
}
}
}, params.row[i.time])
}
//非标识的数据就通过 key值进行匹配渲染
return h('div',params.row[i.time])
},
})
// 当rows为空时 只渲染表头
}else{
col.map((i,index) => {
if (index == 0) {
col.push({
title: `${this.$t('applePay.shift')}/${this.$t('applePay.date')}`,
key: "tips",
minWidth: 120,
align: 'center'
})
}
col.push({
title: `${i.time.substring(4)}\t(${(this.weekDay.find(m => m.code === i.week)).message})`,
minWidth: 150,
align: 'center',
key:`${i.time}`
})
})
}
this.$set(this.table,{columns:col,data: result || []})
上面的代码就实现了当用户选择不同条件查询数据时,页面能够根据后端返回数据去渲染动态的表格。
这个需求如果和后台沟通好了数据接口。实现起来还是比较容易的。最重要的就是:data
中的值与表头中对应的key值相匹配。因此后台返回的rows
数据结构中的key
一定需要与他返回给你的动态列的某个字段的值相匹配
附上实现效果图
最后
文章若有不足之处,还请大家批评指出。
感谢您观看此篇文章 希望能给个👍评论收藏三连!你的点赞就是我写作的动力。