前言
大家都知道 element 表格组件的表头是静态写死的,我们在渲染数据时只需要将接口返回的数组动态绑定给 data 属性,然后再通过 prop 去对应字段项即可;但是静态的表头并不能满足一些特殊的使用场景,所以我们需要将它变成活的,也就是动态渲染表头,然后再将表格中的数据一一对应表头。
实现效果:
实现思路:
与静态表格返回的数据格式不同(如下图),动态表格一般会返回两个数组,分别对应表头数据、表格数据,我们需要将表头的数组在 <el-table-column></el-table-column>
中进行循环,用 :label
绑定循环的表头字段名,用 :prop
绑定表格中的字段名。
表头数据格式:
表格数据格式:
表格中用到的属性:
属性 | 描述 | 类型 | 默认值 |
---|---|---|---|
highlight-current-row | 是否要高亮当前行 | boolean | false |
cell-style | 改变单元格样式 | Function({row, column, rowIndex, columnIndex})/Object | – |
下面是我做的一个简单小实例,其中不止包含动态表格,还有其他方面的一些小功能(根据条件让单元格变色、根据条件控制单元格是否可编辑)
源码如下:
<template>
<div>
<el-dialog title="编辑" :visible.sync="centerDialogVisible" width="80%">
<el-table class="tableBox" :data="tableData" align="center" border style="width: 100%;" :cell-style="myclass" highlight-current-row>
<el-table-column align="center" v-for="(item, index) in headData" :key="index" :prop="item.value" :label="item.zwname">
<template slot-scope="scope">
<!--// 通过 v-if="!item.sfkgg" 控制是否可编辑单元格 //-->
<el-input v-if="!item.sfkgg" v-model="scope.row[index] && scope.row[index].value" clearable />
<span>{{scope.row[index] && scope.row[index].value}}</span>
</template>
</el-table-column>
</el-table>
<div>
<el-button type="primary" @click="present ">提交</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
centerDialogVisible: true, //弹框显隐状态
// 模拟表头数据
headData: [
{
zwname: "id", //表头
sfkgg: true, //判断单元格是否可编辑
sfcb: null, //判断字体是否变色
},
{
zwname: "姓名",
sfkgg: true,
sfcb: null,
},
{
zwname: "性别",
sfkgg: false,
sfcb: true,
},
{
zwname: "年龄",
sfkgg: false,
sfcb: true,
},
{
zwname: "地址",
sfkgg: false,
sfcb: true,
},
{
zwname: "联系方式",
sfkgg: false,
sfcb: true,
},
],
// 模拟表格数据
tableData: [
[
{
zwname: "样品编号",
zdm: "ypbh",
value: "id20200719",
sfkgg: true,
sfcb: null,
},
{
zwname: "样品名称",
zdm: "ypmc",
value: "小明",
sfkgg: true,
sfcb: null,
},
{
zwname: "分配省公司",
zdm: "fpsgs",
value: "男",
sfkgg: true,
sfcb: null,
},
{
zwname: "受检单位",
zdm: "sjdw",
value: "20",
sfkgg: true,
sfcb: null,
},
{
zwname: "油号",
zdm: "yhbh",
value: "北京昌平",
sfkgg: true,
sfcb: null,
},
{
zwname: "抽样地点",
zdm: "cydd",
value: "18812349874",
sfkgg: true,
sfcb: false,
},
],
[
{
zwname: "样品编号",
zdm: "ypbh",
value: "id20220102",
sfkgg: true,
sfcb: null,
},
{
zwname: "样品名称",
zdm: "ypmc",
value: "小红",
sfkgg: true,
sfcb: null,
},
{
zwname: "分配省公司",
zdm: "fpsgs",
value: "女",
sfkgg: true,
sfcb: false,
},
{
zwname: "受检单位",
zdm: "sjdw",
value: "18",
sfkgg: true,
sfcb: null,
},
{
zwname: "油号",
zdm: "yhbh",
value: "北京海淀",
sfkgg: true,
sfcb: null,
},
{
zwname: "抽样地点",
zdm: "cydd",
value: "18856432547",
sfkgg: true,
sfcb: null,
},
],
[
{
zwname: "样品编号",
zdm: "ypbh",
value: "id20220717",
sfkgg: true,
sfcb: null,
},
{
zwname: "样品名称",
zdm: "ypmc",
value: "小蓝",
sfkgg: true,
sfcb: null,
},
{
zwname: "分配省公司",
zdm: "fpsgs",
value: "未知",
sfkgg: true,
sfcb: null,
},
{
zwname: "受检单位",
zdm: "sjdw",
value: "21",
sfkgg: true,
sfcb: false,
},
{
zwname: "油号",
zdm: "yhbh",
value: "北京朝阳",
sfkgg: true,
sfcb: null,
},
{
zwname: "抽样地点",
zdm: "cydd",
value: "16634219856",
sfkgg: true,
sfcb: null,
},
],
],
};
},
mounted() {},
methods: {
//根据条件修改单元格字体样式(sfcb字段为false且不为null时)
myclass({ row, columnIndex }) {
if (row[columnIndex] && !row[columnIndex].sfcb && row[columnIndex].sfcb != null ) {
return "color: red";
}
},
// 提交操作
present() {
let result = [];
// 通过双层循环拿到所需字段
this.tableData.forEach((item) => {
let data = {};
item.forEach((e) => {
// 将字段名、字段值以键值对的形式赋值
data[e.zdm] = e.value;
});
// 每一行数据为一个对象添加到数组中 [{},{},{},...]
result.push(data);
});
console.log(result, "参数");
// 执行接口操作
},
},
};
</script>
<style scoped>
.tableBox {
margin-bottom: 20px;
}
/* 通过显隐控制input框的状态 */
.tableBox .el-input {
display: none;
}
.tableBox .current-row .el-input {
display: block;
}
.tableBox .current-row .el-input + span {
display: none;
}
</style>
拓展
有关于动态表格与其他组件结合使用的操作,大家可移步博主另一篇文章(vue基于el-timeline组件实现动态表格时间线)