最终效果如下
页面只需要设置两个参数(适用于element及antd)
columnSetting // 是否显示列设置按钮
name="TtableColumnSet" // 区分储存本地表头数据(保证其唯一性)
一、element具体代码如下
1、html(新建一个columnSet.vue页面)
<template>
<el-dropdown trigger="click" placement="bottom">
<el-button icon="el-icon-s-operation" size="small">列设置</el-button>
<el-dropdown-menu divided slot="dropdown">
<span class="title">列设置</span>
<draggable class="t_table_column_setting_dropdown" v-model="columnSet">
<el-checkbox
v-for="(col, index) in columnSet"
:key="col.prop"
@click.native.stop
:checked="!col.hidden"
:disabled="col.checkBoxDisabled"
@change="checked => checkChanged(checked, index)"
>{{ col.label }}</el-checkbox>
</draggable>
</el-dropdown-menu>
</el-dropdown>
</template>
2、js
<script>
import draggable from 'vuedraggable'
export default {
name: 'ColumnSet',
components: {
draggable
},
props: {
columns: {
type: Array,
default: () => []
},
title: {
type: String,
default: ''
},
name: {
type: String,
default: ''
}
},
data () {
const columnSet = this.getColumnSetCache()
this.$emit('columnSetting', columnSet)
return {
columnSet
}
},
watch: {
columnSet: function (n) {
this.$emit('columnSetting', n)
localStorage.setItem(`t-ui:TTable.columnSet-${this.name || this.title}`, JSON.stringify(n))
}
},
methods: {
getColumnSetCache () {
const value = localStorage.getItem(`t-ui:TTable.columnSet-${this.name || this.title}`)
return value ? JSON.parse(value) : this.initColumnSet()
},
initColumnSet () {
const columnSet = this.columns.map((col, index) => ({
label: col.label,
prop: col.prop,
hidden: false,
checkBoxDisabled: false
}))
return columnSet
},
checkChanged (checked, index) {
this.$set(this.columnSet, index, { ...this.columnSet[index], hidden: !checked })
let obj = {}
this.columnSet.map(val => {
val.hidden in obj || (obj[val.hidden] = [])
obj[val.hidden].push(val.hidden)
})
if (obj.false.length < 2) {
this.columnSet.map((val, key) => {
if (!val.hidden) {
this.$set(this.columnSet, key, { ...this.columnSet[key], checkBoxDisabled: true })
}
})
} else {
this.columnSet.map((val, key) => {
if (!val.hidden) {
this.$set(this.columnSet, key, { ...this.columnSet[key], checkBoxDisabled: false })
}
})
}
}
}
}
</script>
3、scss
<style lang="scss" scoped>
.el-dropdown-menu {
padding: 15px;
font-size: 14px;
.title {
font-weight: bold;
}
::v-deep .el-checkbox__input.is-checked + .el-checkbox__label {
color: #262626;
}
.t_table_column_setting_dropdown {
display: flex;
flex-direction: column;
max-height: 300px;
overflow-y: auto;
}
}
</style>
4、关于插件vuedraggable(为了方便antd),其实element可以用el-tree代替拖动
主要是:elementUI给了一个自定义节点的插槽,而antd没有,需要增加许多操作,才能满足 故:用了这个第三方插件
如何引入在table组件中
<!--列设置按钮-->
<column-set
v-if="columnSetting"
v-bind="$attrs"
:columns="columns"
@columnSetting="v => columnSet = v"
/>
计算属性中需要添加以下代码
computed: {
columnByProp () {
return this.columns.reduce((acc, cur) => {
acc[cur.prop] = cur
return acc
}, {})
},
renderColumns () {
return this.columnSet.length > 0 ? this.columnSet.reduce((acc, cur) => {
if (!cur.hidden) {
acc.push(this.columnByProp[cur.prop])
}
return acc
}, []) : this.columns
}
最终Element table组件如图所示
二、antd具体代码
1、跟element一样只是table的column的参数不一样
elementUi的columns配置是{prop: 'name', label: '姓名'}
antdUi的columns配置是{dataIndex: 'name', title: '姓名'}