阅读 896

Ant Design Table自适应列宽,就是这么简单!

前言

目前在弄一个动态表格的项目,但由于没法知道每个列具体的内容,无法确定表格的列宽,而统一的设定会导致有的列内容很挤,有的列内容很空洞,整体视觉较差。

分析问题

Ant Design的Table组件,column在不设置width的时候,所有列会平分table的宽度,导致有的表头显示有问题,所以我们肯定需要指定每个列的列宽。现在问题是如何精确的算出后台返回字符串长度的像素值(px)

Q: 能不能根据后台返回字符数来确定列宽?
A: 不能。首先我们没法知道后台返回的字符含有的类型,是纯中文还是含有英文,数字,特殊字符等。这会让我们计算不准确

解决问题

本文使用canvas画布来实现对字符串的测量。

前置知识

canvas  [传送门]  
创建一个canvas对象
document.createElement("canvas")
HTMLCanvasElement.getContext()方法获取这个元素的context——图像稍后将在此被渲染
CanvasRenderingContext2D.measureText() 方法返回一个关于被测量文本TextMetrics 对象包含的信息(例如它的宽度TextMetrics.width)。

**注意:** <canvas> 元素本身并没有绘制能力(它仅仅是图形的容器) - 您必须使用脚本来完成实际的绘图任务。 getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性 复制代码

以下为测量文本实际长度的方法

// 默认字体为微软雅黑 Microsoft YaHei,字体大小为 14px function getTextWidth(text, font="14px Microsoft YaHei") {   const canvas = document.createElement("canvas");   let context = canvas.getContext("2d");    context.font = font   let textmetrics = context.measureText(text)   return textmetrics.width; } 复制代码

自适应列宽表格

第一版

// 定义一个 Map 接收每列的长度值   let widthMap = new Map() // columns 为动态表格的表头数组 data为展示数据的数组  //作用是遍历所有数据拿到长度最长的一条记下他的宽度   data.forEach(target => {     for(let key in target) {       if(target.hasOwnProperty(key)) {         let keyWidth = getTextWidth(target[key])         let curValue = widthMap.get(key)         // 字段有值就放入数组         widthMap.set(key, Math.max(curValue,keyWidth))       }     }   }) //遍历表头,拿到对应表头的宽度与对应表头下内容比对,取最大值作为列宽,这样可以确保表头不换行。35为表头title左右的padding + border columns.map((item)=>{     // title,dataIndex为 ant design Table对应参数     let textWidth = getTextWidth(item.title)      if(widthMap.get(item.dataIndex) < textWidth) {       widthMap.set(item.dataIndex, textWidth)     }     return item.width = Math.ceil(widthMap.get(item.dataIndex)) + 35 }) 最后组件为 <Table    columns={columns}   dataSource={data}   bordered   rowKey={record => record.id} /> 复制代码

优点: 每列内容都能一目了然看全
缺点: 每一行由于后台返回内容长度不一样会导致有的行会比较空洞

image.png 适用范围: 内容长度比较均匀的列表。

第二版

  // 定义一个 Map 接收每列的长度值   let widthMap = new Map()   // columns 为动态表格的表头数组 data为展示数据的数组    //作用是遍历所有数据拿到长度,记下每一列的宽度   data.forEach(target => {     for(let key in target) {       if(target.hasOwnProperty(key)) {         let keyWidth = getTextWidth(target[key])         // 字段有值就放入数组          widthMap.has(key) ? widthMap.set(key,widthMap.get(key).concat(keyWidth)) : widthMap.set(key,[].concat(keyWidth ? keyWidth : [] ))       }     }   })       // 计算平均值,保证列宽尽量保持均衡   for(let [mapKey] of widthMap) {     let valueArr = widthMap.get(mapKey)     let len = valueArr.length     let value = valueArr.reduce((acc, cur) => acc + (cur ? 1/cur : 1),0)     widthMap.set(mapKey, len/value)   }   //遍历表头,拿到对应表头的宽度与对应表头下内容比对,取最大值作为列宽,这样可以确保表头不换行。35为表头title左右的padding + border   columns.map((item)=>{     // title,dataIndex为 ant design Table对应参数     let textWidth = getTextWidth(item.title)      if(widthMap.get(item.dataIndex) < textWidth) {       widthMap.set(item.dataIndex, textWidth)     }     return item.width = Math.ceil(widthMap.get(item.dataIndex)) + 35   }) 最后组件为 <Table    columns={columns}   dataSource={data}   bordered   rowKey={record => record.id} /> 复制代码

优点: 每列列宽相对合理,且视觉上比较美观

image.png

总结

总的来说比较符合要求。若表格数据量较大时,此方法计算量也会相应增加,建议数据量大时,可以取前20行数据作为标准计算列宽均值。

如有帮助,请点个❤ 谢谢!
完结撒花~~


作者:我要怎么学啊
链接:https://juejin.cn/post/7068937960296546334

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐