(编辑:jimmy 日期: 2024/12/29 浏览:2)
一、分析需求
这里先上一张图说明 需求 :
根据后端返回的数据 ( res 是一个数组,它的元素是一个对象,对象里面的 ext
属性是一个对象,它又包含了, default
、 free
和 pay
三个属性,且这三个都是数组格式。):
渲染出一个这样子的 表格
:
res
数据:
res
的每一个元素的直接属性 name
(即为邮费模板名称,比如成都运费模板),
res
的 ext
属性下的三个数组 default
、 free
、 pay
,每一个数组要大的一行(这一行中,第一列是运送到的地址的名字,这里定义的是 area
属性,但后端是未给到这个字段的,可自己处理数据添加该字段 ,这里就不细说了。) 这个 area
属性占据的这一列,在页面的展示效果 应该是多行合并的效果。
二、代码实现:
<template> <div class="layout"> <el-table :data="res" > <el-table-column prop="name"> <template slot-scope="scope"> <div class="tab_header"> <span style="font-weight:600;">{{scope.row.name}}</span> <div class="operate"> <span @click="handleEdit(scope.$index, scope.row)">修改</span> <span @click="handleDelete(scope.$index, scope.row)">删除</span> </div> </div> <!-- 这里要实现 多个表格共用一个表头,故需做判断,当表格要渲染的数据为default这个数组的时候,才显示表头的label值 --> <!-- 注意:当label无值的时候,还是会占用空间,故当前表格在页面上会出现一个代表表头的空行,需要手动更改(重写)Element表格的 thead样式 --> <div v-for="item in (scope.row.ext)" :key="item.id"> <el-table :data="item" border :class="item!==scope.row.ext.default" style="box-sizing: border-box;border-top:none;" :span-method="objectSpanMethod"> <el-table-column :label="item===scope.row.ext.default" prop="area"></el-table-column> <el-table-column :label="item===scope.row.ext.default" prop="weight"></el-table-column> <el-table-column :label="item===scope.row.ext.default" prop="first_price"></el-table-column> <el-table-column :label="item===scope.row.ext.default" prop="weight_incre"></el-table-column> <el-table-column :label="item===scope.row.ext.default" prop="extend_price"></el-table-column> </el-table> </div> </template> </el-table-column> </el-table> </div> </template> <script> export default { data () { return { // res 参考的是后端返回的数据格式, res: [ { id: 1, dealer_id: 0, name: '成都运费模板', type: 1, ext: { default: [{ area: '默认', type: 1, region: '1', weight: '首重d', weight_incre: '续重d', first_price: '运费d', extend_price: '最终运费d' }], free: [{ area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }], pay: [{ area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }] } }, { id: 2, dealer_id: 0, name: '重庆运费模板', type: 2, ext: { default: [{ area: '默认1', type: 1, region: '1', weight: '首重d', weight_incre: '续重d', first_price: '运费d', extend_price: '最终运费d' }], free: [{ area: 'free1', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }, { area: 'free', type: 1, region: '1', weight: '首重f', weight_incre: '续重f', first_price: '运费f', extend_price: '最终运费f' }], pay: [{ area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay1', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }, { area: 'pay', type: 1, region: '1', weight: '首重p', weight_incre: '续重p', first_price: '运费p', extend_price: '最终运费p' }] } } ] } }, methods: { handleEdit (index, row) { console.log(index, row) }, handleDelete (index, row) { console.log(index, row) }, objectSpanMethod ({ row, column, rowIndex, columnIndex }) { if (columnIndex === 0) { if (rowIndex === 0) { let maxLen this.res.forEach(val => { const arr = [val.ext.default.length, val.ext.free.length, val.ext.pay.length] arr.sort((a, b) => a - b)// arr数组 按数字大小从小到大排序 maxLen = arr.pop()// 取出排序后的数组arr中的最后一个元素 }) return { // 这个rowspan应该据 ext的default,pay,free的长度不同来定,取最大长度 rowspan: maxLen, colspan: 1 } } else { return { rowspan: 0, colspan: 0 } } } } } } </script> <style lang="scss"> .layout{ .tab_header{ color:#333; padding:0 5px 0 5px; height:45px; line-height:45px; border:1px solid #eee;display:flex; justify-content: space-between; background:rgb(233, 225, 225); } .operate{ span{ font-size: 14px; margin-right: 20px; margin-right:20px; color:#409EFF; cursor: pointer; } } /* 处理多个表格共用一个表头时,表头处出现多余空行的问题 (label置空后还是占据空间问题) */ .tab-thead-style{ thead{ display: none; } } } </style>
三、知识点总结:
为什么要采用这种方式解决(渲染)?
① . 项目用的UI组件是Element,它的Table表格组件,没有直接处理行的操作。
② . el-table,它是通过注入data对象数组,并在el-table-column 中用prop属性来对应对象中的键名来填入数据,从而渲染出渲染表格。其中el-table-column表示一个列,label属性来定义表格的列名,即对象的一个键名代表一列;
③ . 没想到更优的解决办法,O(∩_∩)O哈哈~
多个表格共用一个表头时,注意:
①. 需做判断,同时注意label的值。
②. 当el-table-column 的属性label无值的时候,还是会占用空间,故当前表格在页面上会出现一个代表表头的空行,需要手动更改(重写)Element表格的 thead样式
table表格嵌套的时候,注意:
① . Element的Table组件可 自定义列模板,主要是利用它实现表格嵌套部分,通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据,更多用法参考官网。
②. Element的Table组件可 合并行或列 ,多行或多列共用一个数据时,可以合并行或列;通过给table传入span-method方法可以实现合并行或列,参考上述代码的 **objectSpanMethod**方法(该表格的第一列需要合并多行——合并渲染表格的data数组的长度那么多行) 或者官网。