vue3笔记(27-3)el-table各种数据展示形式

本篇记录项目中使用过的el-table各种数据展示形式,如不同形式的合并单元格展示的hack写法(自己发明、测试),后期有更好的实现方式也会更新。
更新:el-table 在页面初始化时先出现了暂无数据图片,然后才有 loading,完成后加载数据,针对这一点做了用户体验优化。

合并单元格展示一

列表展示
el-table-column 进行嵌套可实现合并单元格表头,嵌套部分需要加上 rowspan="2"
内容显示需要使用 p 标签进行文本换行,避免文字会自动拼接,使用户迷惑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 <el-table-column label="订单明细" show-overflow-tooltip width="360">
<el-table-column label="产品类型" width="120" rowspan="2">
<template #header> 产品类型 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.order_detail" :key="index">
<p>
<span v-if="item.product_type">{{ item.product_type }}</span>
<span v-else>--</span>
</p>
</template>
</template>
</el-table-column>
<el-table-column label="产品名称" width="120" rowspan="2">
<template #header> 产品名称 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.order_detail" :key="index">
<p>
<span v-if="item.product_name">{{ item.product_name }}</span>
<span v-else>--</span>
</p>
</template>
</template>
</el-table-column>
<el-table-column label="数量" width="120" rowspan="2">
<template #header> 数量 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.order_detail" :key="index">
<p>
<span v-if="item.transaction_number">{{ item.transaction_number }}</span>
<span v-else>--</span>
</p>
</template>
</template>
</el-table-column>
</el-table-column>

再给每行文字添加底部边框之后,因为 cell 自带 padding,需要对 css 进行修改,使得边框两端连续,模拟了表格分割线。

1
2
3
4
5
6
7
8
9
10
11
12
13
.el-table .cell.el-tooltip {
white-space: pre-wrap;
}
.cell {
p:not(:last-child) {
border-bottom: 1px solid #ebeef5;
width: calc(100% + 24px);
margin-left: -12px;
span {
padding-left: 12px;
}
}
}

合并单元格展示二

列表展示
这里左侧文字可以单独使用一列展示文字,右侧数据展示使用单元格套单元格形式,写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<div class="card">
<div class="card-title">
<p><span>CGx_FAULT_STAT_EN</span><span>核组总错状态报错使能寄存器</span></p>
</div>
<div class="card-content">
<el-table
:data="dataList.tableData_cgxen"
v-loading="loadingTable"
:header-cell-style="{ background: '#F4F4F4' }"
border
:span-method="handleSpanMethod"
>
<el-table-column prop="" width="200">
<template #header>
<span></span>
</template>
<template #default="scope">
<span>CGx_FAULT_STAT_EN</span>
</template>
</el-table-column>
<template v-for="column in [0, 1]" :key="column">
<el-table-column :label="`${column}号`" :width="300" :prop="column.toString()">
<el-table-column label="0核组" :prop="`${column}.CG0`" />
<el-table-column label="1核组" :prop="`${column}.CG1`" />
</el-table-column>
</template>
</el-table>
</div>
</div>

合并单元格展示三

需求文档-列表展示
数据格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const opList = [
{
system: 'PTS',
list: [
{
module: '产品追溯台账',
permission: ['全部权限']
},
{
module: '产品信息配置',
permission: ['查看', '编辑']
}
]
},
{
system: 'UMS',
list: [
{
module: '管理员',
permission: ['全部数据权限']
}
]
}
]

这是一个类似树状的展开,我的第一个想法是类似一中展示的那样,使用 p 标签做分隔,写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<el-table :data="opList" :header-cell-style="{ background: '#F5F7FA' }">
<el-table-column
prop="system"
label="子系统名称"
width="120"
show-overflow-tooltip
></el-table-column>
<el-table-column show-overflow-tooltip width="250">
<template #header></template>
<el-table-column label="功能" width="120" rowspan="2">
<template #header> 功能 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.list" :key="index">
<p>{{ item.module }}</p>
</template>
</template>
</el-table-column>
<el-table-column label="操作权限" width="120" rowspan="2">
<template #header> 操作权限 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.list" :key="index">
<div v-for="(p, idx) in item.permission" :key="idx">
<p>{{ p }}</p>
</div>
</template>
</template>
</el-table-column>
</el-table-column>
</el-table>

结果发现 功能 和 操作权限 那两列文字是自动居中对齐的,没有显示出分类的效果。
自动换行效果
优化思路:

  1. 功能 那一栏按照 操作权限 数组去循环,只有第一个元素显示,其余元素做一个占位,同时不用 border-bottom 做分隔,以呈现合并 功能 列单元格的效果。
  2. table 头部用 css 做一个隐藏效果,去掉一栏分两栏的视觉感受。
  3. 实验发现,这里并不需要单元格套单元格的效果,思路2属于浪费精力,舍弃。直接修改单元格。

最终完美实现,效果如下:
 最终效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<el-table
:data="opList"
class="table-special"
:header-cell-style="{ background: '#F5F7FA' }"
border
>
<el-table-column
prop="system"
label="子系统名称"
width="120"
show-overflow-tooltip
></el-table-column>
<el-table-column label="功能" width="120" rowspan="2">
<template #header> 功能 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.list" :key="index">
<div v-if="item.permission.length == 1" class="sp-block">
<p>{{ item.module }}</p>
</div>
<div v-else v-for="(p, idx) in item.permission" :key="idx" class="sp-block">
<p v-if="idx == 0" class="no-border">{{ item.module }}</p>
<p v-else>&nbsp;</p>
</div>
</template>
</template>
</el-table-column>
<el-table-column label="操作权限" width="120" rowspan="2">
<template #header> 操作权限 </template>
<template #default="{ row }">
<template v-for="(item, index) in row.list" :key="index">
<div v-for="(p, idx) in item.permission" :key="idx" class="sp-block">
<p>{{ p }}</p>
</div>
</template>
</template>
</el-table-column>
</el-table>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.el-table .cell.el-tooltip {
white-space: pre-wrap;
}
.sp-block:not(:last-child) {
margin-left: -12px;
p {
border-bottom: 1px solid #ebeef5;
width: calc(100% + 24px);
padding-left: 12px;
}
}
.no-border {
border-bottom: 1px solid transparent !important;
}

页面初始化优化

现状:el-table 在页面初始化时先出现了暂无数据图片,然后才有 loading,完成后加载数据,页面切换时有跳动感,不流畅。需要把“暂无数据”的闪现去掉。
表格为空原版代码如下:

1
2
3
4
5
6
<template #empty>
<div class="table-emypt">
<img src="@/assets/img/emypt.png" alt="" />
<p>暂无数据</p>
</div>
</template>

初始化渲染时默认显示无数据,所以才会出现 slot 中的内容,只需要将内容初始化为空,在获取数据后判断 total = 0时展示即可。

1
2
3
4
5
6
<template #empty>
<div class="table-emypt">
<img :src="getImageURL(emyptImg)" alt="" />
<p>{{ emyptText }}</p>
</div>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
import { getImageURL } from '@/utils/importImages'
const dataList = reactive({
emyptText: '',
emyptImg: '',
})

if (data.total == 0) {
dataList.emyptText = '暂无数据'
dataList.emyptImg = 'emypt.png'
} else {
dataList.tableData = data.data
dataList.pageTotal = data.total
}

vue3笔记(27-3)el-table各种数据展示形式
https://guoningyan.com/2023/08/11/vue3笔记(27-3)el-table各种数据展示形式/
作者
Ningyan Guo
发布于
2023年8月11日
许可协议