使用iview Table生成动态日期表格

909 阅读4分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。

前言

最近接到一个动态渲染table的需求。感觉也挺有意思的,特此分享给大家。

技术栈是ivewUI

实现思路是key值与data值相匹配。

分析需求

  1. 根据用户选择的条件生成一个动态的table,并且table的列和行都是动态的。
  2. table数据根据用户选择的日期月份以及其他条件来进行生成。
  3. 最后一行对整列的数据进行统计。
  4. 统计行的数据点击后可跳转到对应的echarts数据页面。

综合上面的需求我们可以知道 这个table的数据是由用户根据不同的条件查询而生成的,对于前端实现来说,我们应该从后端接口拿到数据进行处理,然后再展示在table中。

实现过程

由于当前项目使用的UI组件库是iview,因此我们可以使用iview中table组件来实现上面所示的需求。

iview table组件中: 我们可以传递 columnsdata这两个参数进行表格的渲染。

<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 一定需要与他返回给你的动态列的某个字段的值相匹配

附上实现效果图

image.png

最后

文章若有不足之处,还请大家批评指出。

感谢您观看此篇文章 希望能给个👍评论收藏三连!你的点赞就是我写作的动力。