Vue版本:2.6.x,AntDesignVue版本:1.7.x(下有v3的修改demo)
在工作中难免会遇到这种情况,较多列的表格展示,如果只想看某些关键列的数据,就需要用到筛选,官方文档的筛选是针对行的数据筛选,没有对列筛选的demo,而这个功能确实比较实用与常见,所以它来了,希望能让不知道的小伙伴少走点冤枉路:
<template>
<a-card>
<a-table :columns="filterColumn" :data-source="dataSource">
// 操作区域的插槽
<span slot="action" slot-scope="text, record">
<a href="#">操作</a>
</span>
// 自定义筛选菜单的插槽
<span slot="filterDropdown">
<a-card>
/* 多选框
options:指定可选项
defaultValue:默认选中的选项
change:变化时回调
*/
<a-checkbox-group :options="checkColumn" :defaultValue="checkColumn" @change="checkChange"/>
</a-card>
</span>
</a-table>
</a-card>
</template>
<script>
export default {
name: 'Demo',
data() {
return {
// 原始表格列配置描述
columns: [
{title: 'name', dataIndex: 'name'},
{title: 'age', dataIndex: 'age'},
{title: 'address', dataIndex: 'address'},
{title: 'action', dataIndex: 'action', width: 147,
/* 配置支持 slot-scope 的属性
customRender: 生成复杂数据的渲染函数,function(当前行的值,当前行数据,索引)
filterDropdown: 自定义筛选菜单
*/
scopedSlots: { customRender: 'action', filterDropdown: 'filterDropdown'}
}
],
// 数据
dataSource: [
{key: '1', name: '张三', age: 18, address: '嘿嘿'},
{key: '2', name: '李四', age: 19, address: '哈哈'},
{key: '3', name: '王五', age: 20, address: '嘻嘻'}
],
// 初始备份的表格列配置描述及过滤后的容器
filterColumn: []
}
},
created() {
// 实例创建完成将columns备份给filterColumns
this.filterColumn = this.columns
},
computed: {
// 用计算属性取出columns的dataIndex,作为多选框的选项数据
checkColumn: function() {
return this.columns.map(item => item.dataIndex)
}
},
methods: {
// 多选框的事件回调
checkChange(checked) {
// 初始是默认全选的,假设此刻点击了name的选择框
console.log(checked) // ['age','address','action']
const columns = this.columns
// 核心部分,数组过滤循环遍历columns,如果选择的值中包含dataIndex则为true并暴露出去,反之亦然
const filterValue = columns.filter(item => {
if (checked.includes(item.dataIndex)){
// 当暴露值为true时,循环遍历的值会赋给filterValue
return true
}
return false
})
// 依旧是假设点击的是name的选择框,暴露的值为[false,true,true,true],所以filterValue中的值没有包含name的那一列
// 然后将值赋给filterColumns
this.filterColumn = filterValue
}
}
}
</script>
PS:2022-12-01更新:
许多小伙伴问到了比如操作那一列,如何不让选择,这个很简单,多选框的数据来源是通过计算属性遍历options取出dataIndex,设置defaultValue默认选择项时可以设置是否为disabled状态,这样子操作列就无法被隐藏了
computed: {
// 用计算属性取出columns的dataIndex,作为多选框的选项数据
checkColumn: function() {
return this.columns.map(item => return item.dataIndex)
},
defaultCheck: function() {
return this.columns.map(item => {
if (item.title === 'action') {
return { label: item.dataIndex, value: item.dataIndex, disabled: true }
} else {
return { label: item.dataIndex, value: item.dataIndex }
}
})
}
}
// template中
<a-checkbox-group :options="checkColumn" :defaultValue="defaultCheck" @change="checkChange"/>
PS:2023-01-06更新
有的小伙伴已经全面拥抱vue3了,ant-design-vue也早早就支持了vue3,小伙伴尝试在v3里迁移文中demo失败,这里我也更新下v3版本如何实现列的自定义隐藏与展示,demo使用Vue版本:3.2.45
,AntDesignVue版本:3.2.15
,需要知道的是ant-design-vue3.x相比于ant-design-vue1.x改动了一些API,如文中用到的checkbox-group的defaultValue取消;table废弃了 column.slots, 新增 v-slot:bodyCell、v-slot:headerCell,用于自定义单元格;新增 column.customFilterDropdown 、v-slot:customFilterDropdown,用于自定义筛选菜单;新增了 v-slot:customFilterIcon 用于自定义筛选按钮,所以相应的写法我们需要变动,但整体逻辑还是相似的,以下代码以composition风格及setup语法糖实现,效果如下图:
<script setup lang="ts">
import {computed, ref} from 'vue'
// 原始列
const columns = [
{title: 'name', dataIndex: 'name', key: 'name'},
{title: 'age', dataIndex: 'age', key: 'age'},
{title: 'address', dataIndex: 'address', key: 'address'},
{title: 'action', dataIndex: 'action', key: 'action', width: 147, customFilterDropdown: true}
];
// 数据
const data = [
{key: '1', name: '张三', age: 18, address: '嘿嘿'},
{key: '2', name: '李四', age: 19, address: '哈哈'},
{key: '3', name: '王五', age: 20, address: '嘻嘻'}
];
// 选择框使用的数据
const checkColumn = computed(() => {
return columns.map(item => {
if (item.dataIndex === 'action') {
return {label: item.dataIndex, value: item.dataIndex, disabled: true}
}
return {label: item.dataIndex, value: item.dataIndex}
})
})
// 默认被选中的数据
const checkValue = columns.map(item => item.dataIndex)
// 备份和被操作列
const filterColumn = ref(columns)
// 选择事件
const checkChange = (checked: string) => {
console.log('click', checked)
const filterValue = columns.filter(item => {
if (checked.includes(item.dataIndex)){
// 当暴露值为true时,循环遍历的值会赋给filterValue
return true
}
return false
})
console.log(filterValue)
filterColumn.value = filterValue
console.log(filterColumn.value)
}
</script>
<template>
<a-table :columns="filterColumn" :data-source="data">
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<span>
<a>操作</a>
<a-divider type="vertical" />
<a>删除</a>
<a-divider type="vertical" />
<span>{{record}}</span>
</span>
</template>
</template>
<template #customFilterDropdown="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }">
<a-card>
<a-checkbox-group :options="checkColumn" v-model:value="checkValue" @change="checkChange"/>
</a-card>
</template>
</a-table>
</template>
PS:2023-02-13更新
有小伙伴问到如何默认隐藏,评论里当时思考的不是很完善,下来后实现了下,主要是改动数据源,有点像是已经做了一次展示/隐藏的操作,如下,template中无改动,此处不作展示:
// 原始列
const columns = [
{ title: "name", dataIndex: "name", key: "name" },
{ title: "age", dataIndex: "age", key: "age" },
{ title: "address", dataIndex: "address", key: "address" },
{ title: "action", dataIndex: "action", key: "action", width: 147, customFilterDropdown: true },
];
// 数据
const data = ref([
{ name: "张三", age: 18, address: "嘿嘿" },
{ name: "李四", age: 19, address: "哈哈" },
{ name: "王五", age: 20, address: "嘻嘻" },
]);
// 选择框使用的数据
const checkColumn = computed(() => {
return columns.map((item) => {
if (item.dataIndex === "action") {
return { label: item.dataIndex, value: item.dataIndex, disabled: true };
}
return { label: item.dataIndex, value: item.dataIndex };
});
});
// 改动一,默认被选中的数据,手动选择哪些值被选中,此前为全选
// 是不是很眼熟,是的他就和checked一样,这里就相当于提前选择了一次
const checkValue = reactive<string[]>(["name", "age", "action"]);
// const checkValue = columns.map(item => item.dataIndex) <= 原
// 改动二,因为有两处用到相同的逻辑,所以抽出一个公共方法
function filterAction(value: Array<string>) {
return columns.filter((item) => {
if (value.includes(item.dataIndex)) {
// 为true时,循环遍历的值会暴露出去
return true;
}
return false;
});
}
// 改动三,备份和被操作的数据,不再是直接拿columns,而是与选择一次的逻辑一样取出来展示
const selectData = filterAction(checkValue);
const filterColumn = ref(selectData);
// const filterColumn = ref(columns) <=原
// 选择事件,改动不大只是抽出了公共方法filterAction
const checkChange = (checked: Array<string>) => {
console.log("click", checked);
const filterValue = filterAction(checked);
filterColumn.value = filterValue;
};
这个demo主要用到了以下知识点:
- JavaScript中数组的过滤filter及判断数组是否包含某一个值includes
- Vue计算属性computed、插槽和生命周期里的created
- antDesignVue用到了card-为了美观,table-数据展示,以及多选框checkbox
此demo参考了
开源低代码平台JeecgBoot的常见案例中的 单表模型示例 点击跳转jeecgboot 开源UI框架vxe-table的复杂表格中的 显示、隐藏、折叠列 点击跳转vxe-table