vue开发table数据合并实现详解
前言
项目中的某个模块,一个勾选表格数据,里面的行数据由于有关联关系,需要多行数据合并,然后勾选时选中一条数据,方便进行下一步业务操作,然后产品经理就指着原型上的表格,说:这里,这里, 数据需要合并......
功能需求有了,里面有个技术实现点 —— 表格数据合并,下面我们就来分析一下这个表格数据合并的实现
思路梳理
方案一 Element 官方 Table 组件数据合并
由于项目用的 Element UI
库, Table 表格
组件刚好有现成的功能,官方还提供了 Demo,代码复制过来直接改一下放到项目,这不还简单
直接翻到 Element UI Table
组件数据合并位置看官方案例,发现里面用了一个 span-method
属性
span-method | 合并行或列的计算方法 | Function({ row, column, rowIndex, columnIndex }) | — | — |
---|
通过如下方式处理合并行或者列
<el-table
border
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width: 800px; margin: 10px 0"
@selection-change="handleSelectionChange"
:span-method="objectSpanMethod"
></table>
methods: {
objectSpanMethod ({ row, column, rowIndex, columnIndex }) {
if (columnIndex === 0) {
if (rowIndex % 2 === 0) {
return {
rowspan: 2,
colspan: 1
}
} else {
return {
rowspan: 0,
colspan: 0
}
}
}
}
}
通过这个函数控制 rowspan
colspan
来实现合并,但是分析数据结构的时候发现两个点
- 这种方案的数据是多条数据合并成一行渲染的方式
- 多行数据合并后,选中行的效果还是一行一行的,不同行的选中效果不一样
实际项目中数据格式是这样的,表格行有对应的ID,每行数据超过20列,每列内容部分可能还比较多,如下例子
[
{
id: '1',
date: '2016-05-03',
name: '张三',
address: '家庭地址:上海市普陀区金沙江路'
},
{
id: '1',
date: '2016-05-03',
name: '张三',
address: '公司地址:北京市朝阳区金台路'
},
{
id: '2',
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 '
}
]
按照这种方式的话,每次请求后端都需要返回大量数据,性能不是很好;不同的列字段还需要动态处理表格单元格的合并, span-method
里面的逻辑得写一大坨, 这个表格合并方案在当前项目中用不是很友好
注意
Demo 里面的是静态数据,如果是动态比较id的合并的方式, span-method 里面逻辑需要单独处理。网上有很多动态对比ID数据实现数据行合并的实现,按需搜索即可,文章下面也提供了两个实现参考链接
那还有更好的实现方案吗?
方案二 Table-column Scoped Slot
首先要满足合并行是一条数据,需要多行展示的数据通过 Table-column Slot
实现,写个循环动态展示数据,如下数据格式
[
{
id: '1',
date: '2016-05-03',
name: '张三',
address: ['家庭地址:上海市普陀区金沙江路', '公司地址:北京市朝阳区金台路']
},
{
id: '2',
date: '2016-05-02',
name: '王小虎',
address: ['上海市普陀区金沙江路 1518 ']
},
{
id: '3',
date: '2016-05-02',
name: '李四',
address: ['广州市xxx区']
}
]
例如需要多行展示的列为 address
, 后端返回的格式为一个数组直接遍历使用 div
渲染
<el-table-column
label="地址"
>
<template slot-scope="scope">
<div
style=""
v-for="(item, index) in scope.row.address"
:key="index"
>
{{ item }}
</div>
</template>
</el-table-column>
得到如下效果
这时候并不是一个多行数据合并的效果,给 div
加个 border-bottom
样式,顺便处理一下渲染时的最后一个 div
不加 border
<el-table-column
label="地址"
class-name="cell-control-type"
label-class-name="cell-control-title"
>
<template slot-scope="scope">
<div
style=""
v-for="(item, index) in scope.row.address"
:key="index"
>
<div
v-if="index === scope.row.address.length - 1"
style=""
>
{{ item }}
</div>
<div
v-else
style="border-bottom: 1px solid #ebeef5;"
>
{{ item }}
</div>
</div>
</template>
</el-table-column>
这时候的表格列有边距问题,看起来还不是一个合并的表格行,接下来我们看下表格内置的边距控制
通过分析 Table
的源码,需要把对应的列的内置 padding
属性去掉,然后让循环遍历数据的 div
宽度充满表格单元格,这时候再给循环遍历的 div
添加对应的边距,去除 Element Table
内置 cell
样式的时候再对应的列上添加了一个自定义 class
类 —— cell-control-type
,这里用来修改 address
当前列的样式,而不影响其他列
由于移除整个列的 padding
, 列头标题位置也受影响了,使用 label-class-name
属性把列 title
的 margin-left
设置一下,就和原生效果一样了
<el-table-column
label="地址"
class-name="cell-control-type"
label-class-name="cell-control-title"
>
<template slot-scope="scope">
<div
style=""
v-for="(item, index) in scope.row.address"
:key="index"
>
<div
v-if="index === scope.row.address.length - 1"
style="padding: 10px"
>
{{ item }}
</div>
<div
v-else
style="border-bottom: 1px solid #ebeef5; padding: 10px"
>
{{ item }}
</div>
</div>
</template>
</el-table-column>
<style>
.cell-control-type {
padding: 0 0 !important;
}
.cell-control-title {
margin-left: 10px;
}
.cell-control-type .cell {
padding: 0 0 !important;
}
</style>
看一下调整后的完整效果,这时候看起来合并效果还不错,也满足产品经理的需求了
注意
修改 Element
原生样式的时候需要写到全局 <style>
中,否则样式修改无效
修改UI库组件源码的时候需要注意当前的样式修改是否影响了其他 .vue
页面的实现效果,尤其公共组件统一修改的时候
小技巧
可以通过给需要修改的组件添加个一个自定义的 class
类,例如修改 Table
组件可以如下写法
.custom-class .table {}
参考链接
Element UI Table 合并行或列
element.eleme.io/#/zh-CN/com…
Element UI Table 动态合并行或列
https://www.jb51.net/article/256955.htm
https://www.jb51.net/article/256947.htm
代码地址
- github.com/gywgithub/v…
以上就是vue开发table数据合并实现详解的详细内容,更多关于vue开发table数据合并的资料请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341