AntDesign – Vue Table组件 实现动态表格、列宽计算(方式二)

  朋友们,按照上文(方式一)思路,实现了动态表格和表头分组,这篇按照方式一的需求,扩展出另一种代码写法;

一、表格头

  表格columns 还是定义在data() {} 中,初始化静态列数组,配置项列由后端接口返回(第二点写动态配置项代码);

  在方式一基础上加了 筛选菜单 功能,因此变化代码部分如下:

 :columns="filterColumns()"
<a-table ref="table" bordered :columns="filterColumns()" :dataSource="tableData" :loading="loading" :pagination="false" :scroll="{y: tableHeight-60, x:'max-content'}" :style="{ height: tableHeight+ 'px' }"></a-table>
// data定义 columns静态列
columns: [ { title:
'单号', dataIndex: 'businessNumber', key: 'businessNumber', width: 200, },{ title: '时间', dataIndex: 'adTimeText', key: 'adTimeText', width: 160, },{ title: '单据类型', dataIndex: 'adTypeText', key: 'adTypeText', width: 120, },{ title: '类型', dataIndex: 'type', key: 'type', width: 120, customRender: (text)=>{ return <span>{text==1?'分明细':'平明细'}</span> } },{ title: '状态', dataIndex: 'adStatus', key: 'adStatus', width: 120, scopedSlots: { filterDropdown: 'ADStatusFilter',customRender: 'ADStatusSlot' }, },{ title: '总额', dataIndex: 'total', key: 'total', width: 90, }, ],

  表头增加筛选菜单功能,因为data() 定义中尽量不用this,所以添加筛选菜单时,放在methods方法上,如下:

// 表头筛选菜单
filterColumns(){ const columns
= deepClone(this.columns) columns.map(item => { if(item.key == 'adStatus'){ this.$set(item, 'filtered', this.adStatus); // 标识数据是否经过过滤,图标会高亮 } return item }) return columns },

  表格状态列加了筛选功能,筛选图标是否高亮由 this.adStatus 值变化,绑定adStatus状态如下:

    <template slot="ADStatusFilter" slot-scope="{ confirm }">
          <SelectSearch v-model="adStatus" :options="adStatusList" @search="val=>{ handleSearch(val,confirm)}"></SelectSearch>
    </template>

二、表格体

  展现内容和上文一样,和方式一的区别在于企微主体名称所在的列需要动态计算宽度,不然渲染就会列错位,解决方式如下:

  关键代码是  getTextWidthFn() 

async queryList(){
      let res = await GetList()
      let {data}=res.data
      let result =data&&data.length?data.sort((a1,a2)=>a1.sort-a2.sort):[]
      let colArr=[]
      // 获取企微主体名称文字的宽度
      const getTextWidthFn = (text)=>{
        const fontfamily = "Microsoft YaHei,PingFang SC"
        const canvas = document.createElement("canvas")
        const ctx = canvas.getContext("2d")
        ctx.font = `14px ${fontfamily}`
        const textMetrics = ctx.measureText(text)
        const actual = Math.abs(textMetrics.actualBoundingBoxLeft) + Math.abs(textMetrics.actualBoundingBoxRight)+32 // 加表头滚动条边距32
        return Math.ceil(Math.max(textMetrics.width, actual))
      }
      result.forEach((el,index)=>{
        let i=index+1
        let textWidth = getTextWidthFn(el.subjectName)
        textWidth = textWidth&&textWidth<132?'132px': textWidth+'px' // 如果计算出文字宽度小于132,固定宽度为132px
        colArr.push({
          title: el.subjectName,
          dataIndex: 'alreadyTotal'+i, // 企微主体名称列索引值
          key: 'alreadyTotal'+i, // 注意i值
          scopedSlots: { customRender: 'alreadyTotalSlot' },
          width: textWidth,
          customCell: () => {
            return {
              style: {
                width: textWidth
              }
            }
          },
          id: el.subjectId,
        })
      })
      if(JSON.stringify(this.accountData)!=JSON.stringify(colArr))this.columns=this.columns.concat(colArr)
      this.accountData=colArr
      this.$nextTick(()=>{
        this.queryPage()
      })
    },

  代码思路是: 通过canvas设置文字大小和内容,通过 ctx.measureText 计算出文字宽度,赋值给列宽,然后设置单元格属性;

    列数组计算完后,合并静态列和动态列数组,渲染到表格上。

  表格列动态绘制及列宽展示代码,结束啦,哈哈哈~

  上文链接: https://www.cnblogs.com/anniey/p/18569807

请登录后发表评论

    没有回复内容