最近遇到一个需求,要求可以动态控制 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>
复制
效果如下图:
默认只展示姓名和地址列
缓存勾选的列
可以将日期列选中,在列表中进行展示
缓存勾选的列