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.45AntDesignVue版本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主要用到了以下知识点:
  1. JavaScript中数组的过滤filter及判断数组是否包含某一个值includes
  2. Vue计算属性computed、插槽和生命周期里的created
  3. antDesignVue用到了card-为了美观,table-数据展示,以及多选框checkbox
此demo参考了

开源低代码平台JeecgBoot的常见案例中的 单表模型示例 点击跳转jeecgboot
开源UI框架vxe-table的复杂表格中的 显示、隐藏、折叠列 点击跳转vxe-table

Logo

基于 Vue 的企业级 UI 组件库和中后台系统解决方案,为数万开发者服务。

更多推荐