【low-ui-vue】实现原生可扩展动态表格组件

2024-06-22 21:36

本文主要是介绍【low-ui-vue】实现原生可扩展动态表格组件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

22e264ba9682a7be8190bc863d7cf47c.jpeg

c63d832215462fbbd6909a772a6428b1.gif

本文字数:3520

预计阅读时间:20分钟

b1912a46cf8d3f586c228bc88bafdc59.png

所谓动态列的表格,就是列数不固定。像广为使用的elementUI的table组件就是表头写死的,这种也叫列数固定的表格。

01

效果

b5a360ed003724f3607d5573190e41d9.jpeg03f1c9ad06a04eb0783593ce7ad9cefe.jpeg

c2a7c6aa611f5c5b9dd3f4432300b64e.jpeg

当然,动态性增加了,当然要做出一定“牺牲”。这是表格组件的表头和表内容的数据格式不太一样了——我们把它分为两个数组传入:

02

数据传入

columns: [ // 表头{ title: 'Full Name', width: 132, dataIndex: 'name', fixed: 'left' },{ title: 'Age', width: 100, dataIndex: 'age' },{ title: 'address1', dataIndex: 'address1', key: '1', width: 150 },{ title: 'address2', dataIndex: 'address2', key: '2', width: 150 },//...{ title: '操作', dataIndex: 'do', width: 172, fixed: 'right' }
],
data: [{ key: 1, name: '章三', age: '18', class: '2班', address1: '111', address2: '222', address3: '333', address4: '444', address5: '555', address6: '666', address7: '777', isEdit: false },{ key: 2, name: '章三2', age: '18', class: '2班', address1: '111', address2: '222', address3: '333', address4: '444', address5: '555', address6: '666', address7: '777', isEdit: false }
]

可以看到,“表头”数组中的title属性就是表头应该展示的内容,dataIndex属性就是和“表内容”data数组中关联的属性。它的值如果作为key出现在表内容数组中,则表内容这一项会展示在表格中,反之则不会。

这样的数据格式也是方便了动态的特点:前端可以根据特定的场景对表头和内容单独分别处理、二次开发比如“checkbox”也可以针对数据格式做校验。

这里也是为另一种情况考虑:表头和表内容数组都由后端提供,并不是所有返回的东西都要展示,也不是没有展示的东西都不需要,比如某一行数据的修改需要id—— 数据由后端提供,样式由前端修改。

我们继续分析数据:我们还看到了fixed属性和width属性。前者是用来判断超出表格宽度时最左侧和最右侧是否固定在两侧,这个属性只能在表头数组的第一项和最后一项中出现后者是控制当前列的宽度。这个属性也只能在表头数组中出现!而表内容数组中出现了另一个值:isEdit。它用来判断当前行是否“在修改”。后面会看到,我们给表内容的每一项v-if了一个input或者自定义component。

03

基础版实现

表格整体当然是用了原生的table、tr、td实现。

虽然表头看似是一个单独的内容,但是为了样式考虑,我们并没有放在th中,而是作为一个普通的td,反之样式可以自定义:

<div class="table-container" ref="tableContainer" @scroll="handleScroll"><table><colgroup><col v-for="(column, index) in columns" :key="index":style="{ width: column.width + 'px', minWidth: column.width + 'px' }":class="{ 'fixed-left': index === 0, 'fixed-right': index === columns.length - 1 && column.fixed === 'right' }" /></colgroup><tbody><tr><td v-for="(column, index) in columns" :key="index":style="{ width: column.width + 'px', minWidth: column.width + 'px' }":class="{ 'fixed-left': index === 0, 'fixed-right': index === columns.length - 1 && column.fixed === 'right', 'header-cell': true }"><div class="fixed-item"><div style="display: flex;align-items: center;height: 22px;line-height: 22px;">{{ column.title }}</div></div></td></tr><tr v-for="(row, rowIndex) in data" :key="rowIndex"><td v-for="(column, columnIndex) in columns" :key="columnIndex":class="{ 'fixed-left': columnIndex === 0, 'fixed-right': columnIndex === columns.length - 1 && column.fixed === 'right' }"><div class="fixed-item"><template v-if="column.dataIndex === 'do'"><div style="display: flex;align-items: center;height: 22px;line-height: 22px;"><slot :row="row"></slot></div></template><template v-else-if="!row.isEdit && !row.component"><div style="display: flex;align-items: center;height: 22px;line-height: 22px;">{{ row[column.dataIndex] }}</div></template><component :is="row.component" v-bind="row.props" v-else-if="row.component" /><template v-else><div style="display: flex;align-items: center;"><a-input v-model="row[column.dataIndex]" placeholder="" allow-clear /></div></template></div></td></tr></tbody></table>
</div>

这操作看着很常规:

  • 在表格的HTML结构中,使用v-for指令来循环生成列和行。v-for="(column, index)in columns"用于生成列,v-for="(row, rowIndex)in data"用于生成行;

  • 每个单元格的内容由row[column.dataIndex]决定,其中column.dataIndex是列的属性名,row是当前行的数据对象。

为了简化代码和防止数据冲突,我用了<colgroup>和<col>标签,以达到“只需要在表头数据中添加width即可”的效果。从性能角度考虑:使用<colgroup>和<col>元素也可以帮助浏览器更有效地渲染表格。由于列的宽度和样式是在<col>元素中定义的,浏览器可以提前计算表格的布局,从而提高渲染性能!

.table-container {overflow-x: auto;max-width: 100%;position: relative;td {padding: 0;background-color: #fff;border-bottom: 0.9px solid #eee;.fixed-item {padding: 13px;&.header-cell {font-size: 14px;color: rgba(0, 0, 0, 0.85);font-weight: 500;}}}
}.fixed-left {position: sticky;left: 0;width: 142px;align-items: center;z-index: 9;.fixed-item {display: block;}
}.fixed-right {position: sticky;right: 0;width: 172px;align-items: center;z-index: 9;.fixed-item {display: block;}
}.header-cell {background-color: #fafafa !important;
}

同时,监听了表格的scroll事件,在滚动的时候动态添加删除某个元素 —— 让表格左右侧列的阴影效果在需要的时候才展示:

handleScroll(event) {const container = event.target;const scrollLeft = container.scrollLeft;const maxScrollLeft = container.scrollWidth - container.clientWidth;// 根据滚动位置添加或移除阴影样式if (scrollLeft === 0) {container.classList.add('scroll-left');container.classList.remove('scroll-right');} else if (scrollLeft >= maxScrollLeft) {container.classList.add('scroll-right');container.classList.remove('scroll-left');} else {container.classList.add('scroll-left');container.classList.add('scroll-right');}
}

对应的css样式:

/* 添加阴影样式 */&.scroll-left .fixed-right {border-bottom: 0.1px solid transparent !important;.fixed-item {width: 100%;height: 100%;box-shadow: 1px 57px 22px 0 rgba(0, 0, 0, 0.2);}}&.scroll-right .fixed-left {border-bottom: 0.1px solid transparent !important;.fixed-item {width: 100%;height: 100%;box-shadow: -1px 57px 22px 0 rgba(0, 0, 0, 0.2);}}

到此为止,如开头所示就实现了。

使用如下:

<biaoge :columns="columns" :data="data"><template v-slot:default="{ row }"><a-button style="height: 22px;line-height: 22px;" type="link" @click="toggleEdit(row)">{{ row.isEdit ? '完成' : '修改' }}</a-button></template>
</biaoge>

04

进阶?

上面的代码虽然我们只在滚动中操作了class,并没有直接操控 style,但它仍然是监听了scroll。带来了很大的性能隐患。

能不能完全用css实现阴影的动态显示?能!

什么是“阴影动态显示”?在表格内容超出可视区域左右滚动时对超出部分有阴影提示效果。

af3c46b0b72231b79dd5b4f6e29abecf.png

4.1

在CSS3的时代,我们可以在想要加滚动条的地方外包裹一层div,为其设置overflow:hidden,内部用calc()函数动态计算width使其溢出。这可以有效解决IE下兼容性问题。我们现在已经很少通过滚动条来滚动页面了(更多的是使用触摸手势),但滚动条对于元素内容可滚动的提示作用仍然是十分有用的,哪怕对于那些没有发生交互的元素也是如此;而且这种提示方式十分巧妙。

假如有一个ul、li列表:

<ul><li>Ada Catlace</li><li>Alan Purring</li><li>Schrödingcat</li><li>Tim Purrners-Lee</li><li>WebKitty</li><li>WebKitty</li><li>Json</li><li>Void</li>
</ul>

对 ul 来说:

overflow: auto;
width: 10em;
height: 8em;
padding: .3em .5em;
border: 1px solid silver;

我们用一个径向渐变在顶部添加一条阴影:

background: radial-gradient(at top, rgba(0,0,0,.2),transparent 70%) no-repeat;
background-size: 100% 15px;

现在,当我们滚动列表时,这条阴影会一直停留在相同的位置。这正是背景图像的默认行为:它的位置是相对于元素固定的!不论元素的内容是否发生了滚动。这一点也适用于background-attachment: fixed的背景图像。它们唯一的区别是,当页面滚动时,后者是相对于视口固定的。有没有办法让背景图像跟着元素的内容一起滚动呢?

现在常见的值只有inherit、scroll、fixed,但是从W3C文档中可以看到:后来为background-attachment属性增加了一个新的关键字,叫作local。如果将此属性应用到这条阴影上,它会带给我们正好相反的效果:当我们滚动到最顶端时,能看到一条阴影;但当我们向下滚动时,这条阴影就消失了。

我想到了一个很常用的hack:我们需要两层背景:一层用来生成那条阴影,另一层基本上就是一个用来遮挡阴影的白色矩形,其作用类似于遮罩层。生成阴影的那层背景将具有默认的 background-attachment值(scroll),因为我们希望它总是保持在原位。我们把遮罩背景的background-attachment属性设置为local,这样它就会在我们滚动到最顶部时盖住阴影,在向下滚动时跟着滚动,从而露出阴影。

background: linear-gradient(white 30%, transparent),radial-gradient(at 50% 0, rgba(0,0,0,.2),transparent 70%);
background-repeat: no-repeat;
background-size: 100% 50px, 100% 15px;
background-attachment: local, scroll;

下方的阴影只需要添加*-gradient的第一个参数,改变方向即可 —— 我们的表格组件也可以这样写:

background: linear-gradient(to right,white 30%, transparent) left / 100% 50px,radial-gradient(at 0 50%, rgba(0,0,0,.2),transparent 72%) left / 100% 15px,linear-gradient(to left, white 15px, hsla(0,0%,100%,0)) right / 100% 50px,radial-gradient(at right, rgba(0,0,0,.2), transparent 72%) right / 100% 15px;
background-repeat: no-repeat;
background-attachment: scroll, local, scroll, local;

620b848f649029a1a9346fb547988ffa.jpeg

这篇关于【low-ui-vue】实现原生可扩展动态表格组件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1085480

相关文章

慢sql提前分析预警和动态sql替换-Mybatis-SQL

《慢sql提前分析预警和动态sql替换-Mybatis-SQL》为防止慢SQL问题而开发的MyBatis组件,该组件能够在开发、测试阶段自动分析SQL语句,并在出现慢SQL问题时通过Ducc配置实现动... 目录背景解决思路开源方案调研设计方案详细设计使用方法1、引入依赖jar包2、配置组件XML3、核心配

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B

Python位移操作和位运算的实现示例

《Python位移操作和位运算的实现示例》本文主要介绍了Python位移操作和位运算的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 位移操作1.1 左移操作 (<<)1.2 右移操作 (>>)注意事项:2. 位运算2.1

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

SpringMVC 通过ajax 前后端数据交互的实现方法

《SpringMVC通过ajax前后端数据交互的实现方法》:本文主要介绍SpringMVC通过ajax前后端数据交互的实现方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价... 在前端的开发过程中,经常在html页面通过AJAX进行前后端数据的交互,SpringMVC的controll