本篇记录项目中使用过的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 进行修改,使得边框两端连续,模拟了表格分割线。
| .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>
|
结果发现 功能 和 操作权限 那两列文字是自动居中对齐的,没有显示出分类的效果。
优化思路:
- 功能 那一栏按照 操作权限 数组去循环,只有第一个元素显示,其余元素做一个占位,同时不用 border-bottom 做分隔,以呈现合并 功能 列单元格的效果。
- table 头部用 css 做一个隐藏效果,去掉一栏分两栏的视觉感受。
- 实验发现,这里并不需要单元格套单元格的效果,思路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> </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>
|
| .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,完成后加载数据,页面切换时有跳动感,不流畅。需要把“暂无数据”的闪现去掉。
表格为空原版代码如下:
| <template #empty> <div class="table-emypt"> <img src="@/assets/img/emypt.png" alt="" /> <p>暂无数据</p> </div> </template>
|
初始化渲染时默认显示无数据,所以才会出现 slot 中的内容,只需要将内容初始化为空,在获取数据后判断 total = 0时展示即可。
| <template #empty> <div class="table-emypt"> <img :src="getImageURL(emyptImg)" alt="" /> <p>{{ emyptText }}</p> </div> </template>
|
| 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 }
|