vue框架中表格列宽自适应如何实现,方法是什么
Admin 2022-07-19 群英技术资讯 1114 次浏览
Element UI 是 PC 端比较流行的 Vue.js UI 框架,它的组件库基本能满足大部分常见的业务需求。但有时候会有一些定制性比较高的需求,组件本身可能没办法满足。最近在项目里就碰到了。
很多页面都需要用到表格组件el-table。如果没有给el-table-column指定宽度,默认情况下会平均分配给剩余的列。在列数比较多的情况,如果el-table宽度限定在容器内,单元格里的内容就会换行。强制不换行,内容要么在单元格内滚动,要么就会溢出或被截断。
产品想要的效果是:内容保持单行显示,列间距保持一致,表格超出容器允许水平滚动。el-table-column是支持设置固定宽度的,在内容宽度可预知的情况下,也能满足这个需求。问题就在于如何让列宽动态适应内容的宽度。在官方文档也没找到这样的选项,应该是组件本身不支持。
于是想到了动态计算内容宽度的方案。网上也有人提过这个思路,做法是根据内容字符数来计算宽度。这种方法有几个局限:
我采用了另一种思路,还是动态计算内容宽度,但是根据实际渲染后的 DOM 元素宽度,这样就能解决上面三个问题。
具体怎么做呢?通过查看渲染后的 DOM 元素发现,el-table 的表头和内容分别用了一个原生table,通过colgroup设置每列的宽度。就从这里入手,col的name属性值和对应的 td的class值是一致的,这样就可以遍历对应列的所有单元格,找出宽度最大的单元格,用它的内容宽度加上一个边距作为该列的宽度。
怎么计算内容宽度呢?这是个比较关键的步骤。渲染后的每个单元格有个.cell类,用white-space: nowrap; overflow: auto;设置为不允许换行,内容超出后可滚动,同时设置display: inline-block;以便计算实际内容宽度。这样,最终的宽度可通过.cell元素的scrollWidth属性得到。
function adjustColumnWidth(table) { const colgroup = table.querySelector("colgroup"); const colDefs = [...colgroup.querySelectorAll("col")]; colDefs.forEach((col) => { const clsName = col.getAttribute("name"); const cells = [ ...table.querySelectorAll(`td.${clsName}`), ...table.querySelectorAll(`th.${clsName}`), ]; // 忽略加了"leave-alone"类的列 if (cells[0]?.classList?.contains?.("leave-alone")) { return; } const widthList = cells.map((el) => { return el.querySelector(".cell")?.scrollWidth || 0; }); const max = Math.max(...widthList); const padding = 32; table.querySelectorAll(`col[name=${clsName}]`).forEach((el) => { el.setAttribute("width", max + padding); }); }); }
中间的探索过程比较繁琐,但最终的代码实现却非常简洁。在什么时候触发列宽计算呢?自然是组件渲染完成后。为了方便重用,我采用了 Vue 自定义指令的方式。
Vue.directive("fit-columns", { update() {}, bind() {}, inserted(el) { setTimeout(() => { adjustColumnWidth(el); }, 300); }, componentUpdated(el) { el.classList.add("r-table"); setTimeout(() => { adjustColumnWidth(el); }, 300); }, unbind() {}, });
更进一步,我封装了一个 Vue 插件叫v-fit-columns,已经发布到 npm 仓库,直接安装即可使用。
安装:
npm install v-fit-columns --save
引入:
import Vue from 'vue'; import Plugin from 'v-fit-columns'; Vue.use(Plugin);
使用:
<el-table v-fit-columns> <el-table-column label="No." type="index" class-name="leave-alone"></el-table-column> <el-table-column label="Name" prop="name"></el-table-column> <el-table-column label="Age" prop="age"></el-table-column> </el-table>
源码仓库在这:https://github.com/kaysonli/v-fit-columns ,欢迎各位不吝赐教和 Star!
这个方案多少有点 Hack 的意味,只顾实现需求,可能在其他方面还有点瑕疵,比如渲染完后会稍微闪一下(因为要重新调整宽度,会出现 reflow)。不过从最终实现的效果来看,还算令人满意
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
JS利用循环解决的一些常见问题总结 目录 1. 打印0-100中3的倍数 2. 在页面中写入 1000-2000年中的闰年 3. 打印100以内所有偶数的和 4.求出1-1/2+1/3-1/4……1/100的和 5. 打印三角形 5.1 普通三角形 5.2 倒三角 5.3 等腰三角形 6.等腰梯形 7.输出100-200之间所有的质数 9. 有一个棋盘,有64个方格,在第一个方格里面放1粒芝麻重量是0.00001kg,第二个里面放2粒,第三个里面放4,棋盘上放的所有芝麻的重量 10.在页面上完成以一个九九乘法表 11.打印一个3行
node中如何使用Socket.IO模块?下面本篇文章就来给大家介绍一下在node.js中优雅使用Socket.IO模块的方法,希望对大家有所帮助!
本篇文章给大家带来了关于javascript的相关知识,其中主要介绍了关于JavaScript中的数组方法和循环,具有很好的参考价值,希望对大家有所帮助。
怎样用vue实现点赞动画效果?现在很多网站平台都有点赞功能,这篇文章就给大家分享怎样用vue实现一个好看的点赞动画,当点赞时,同时点亮爱心和增加点赞数,效果如下,感兴趣的朋友就继续往下看吧。
前端开发人员只要了解过vue.js框架可能都知道单文件组件。vue.js中的单文件组件允许在一个文件中定义一个组件的所有内容。这是一个非常有用的解决方案,在浏览器网页中已经开始提倡这种机制。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008