最近遇到一个需求,要求可以动态控制 table 列表中的列的显示与隐藏,并且将选中的列进行存储,下次进入页面仍展示上次勾选的列。
经过查阅资料,实现了这个功能,创建一个Table.vue文件,组件封装代码如下:
<template>
<div>
<el-table
ref="dataTable"
:data="tableData"
header-cell-class-name="headerCell"
cell-class-name="contentCell"
fit
border
lazy
size="mini"
>
<!-- 索引列 -->
<el-table-column type="index" width="50" />
<!-- 描述和操作列 -->
<template v-for="(item, index) in tableHead">
<el-table-column
v-if="tableHead[index].isShow"
:key="index"
:prop="item.columnName"
:label="item.columnTitle"
align="center"
>
<template slot-scope="scope">
<div>{{scope.row[item.columnName]}}</div>
</template>
</el-table-column>
</template>
<!-- 切换显示隐藏列 -->
<el-table-column width="40">
<template slot="header" slot-scope="scope">
<a href="javascript:;">
<el-popover :ref="`popover-${scope.$index}`" width="150" placement="left" trigger="click">
<el-checkbox-group v-model="columnSelecteds">
<el-checkbox
v-for="item in tableHead"
v-show="item.columnTitle"
:key="item.columnTitle"
:label="item.columnTitle"
/>
</el-checkbox-group>
<i slot="reference" class="el-icon-s-grid" />
</el-popover>
</a>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
props: {
tableData: {
type: Array,
required: true,
default: () => []
},
tableHead: {
type: Array,
required: true,
default: () => []
}
},
data() {
return {
columnSelecteds: [] // 已选择的项
}
},
watch: {
/* @title 监听列显示隐藏**/
columnSelecteds(newArrayVal) {
// 计算为被选中的列标题数组
var nonSelecteds = this.tableHead
.filter((item) => newArrayVal.indexOf(item.columnTitle) === -1)
.map((item) => item.columnTitle)
// 根据计算结果进行表格重绘
this.tableHead.filter((item) => {
const isNonSelected = nonSelecteds.indexOf(item.columnTitle) !== -1
if (isNonSelected) {
// 隐藏未选中的列
item.isShow = false
this.$nextTick(() => {
this.$refs.dataTable.doLayout()
})
} else {
// 显示已选中的列
item.isShow = true
this.$nextTick(() => {
this.$refs.dataTable.doLayout()
})
}
})
localStorage.setItem('columnSelecteds', JSON.stringify(newArrayVal))
}
},
created() {
// 初始化要显示的列
if (JSON.parse(localStorage.getItem('columnSelecteds')) && JSON.parse(localStorage.getItem('columnSelecteds')).length) {
this.columnSelecteds = JSON.parse(localStorage.getItem('columnSelecteds'))
} else {
this.tableHead.forEach((item) => {
if (item.isShow) {
this.columnSelecteds.push(item.columnTitle)
}
})
localStorage.setItem('columnSelecteds', JSON.stringify(this.columnSelecteds))
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .headerCell {
padding: 5px 0;
background: #f5f7fa;
color: #606266;
}
::v-deep .contentCell {
padding: 5px 0;
text-align: center;
}
::v-deep .el-table .cell{
white-space: nowrap;
}
.el-checkbox:last-of-type{
margin-right: 30px;
}
</style>
组件用法如下,新建一个index.vue,将Table组件引入使用:
<template>
<div>
<Table
:table-data="tableData"
:table-head="tableHead"
/>
</div>
</template>
<script>
import Table from './components/Table'
export default {
components: {
Table,
},
data() {
return {
// 表头数据
tableHead: [{
'columnName': 'name',
'columnTitle': '姓名',
'isShow': true
}, {
'columnName': 'date',
'columnTitle': '日期',
'isShow': false
}, {
'columnName': 'address',
'columnTitle': '地址',
'isShow': true
}],
// 表格数据
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
}
}
</script>
效果如下图:
默认只展示姓名和地址列
缓存勾选的列
可以将日期列选中,在列表中进行展示
缓存勾选的列