实现背景
由于在项目中需要实现这样一个需求:”对表格列表的某一列进行筛选,包括利用输入搜索、多选实现表格数据的过滤筛选“,由于antd的Table组件可以通过filterDropdown
属性实现自定义筛选菜单,该属性类型为ReactNode | (props: FilterDropdownProps) => ReactNode
,该函数负责渲染图层,需要开发人员自行编写各种交互,这恰好能够满足我们这个需求。
分析实现
分析需求可得到,该自定义筛选菜单包括:
- 头部区域的输入框,该输入框主要负责实现多选框的过滤筛选
- 中间区域的多选框内容,该部分主要负责渲染当前列column的数据数组,以便后续实现表格column的数据筛选
- 底部区域的操作按钮,包括全选checkbox、重置按钮和确定筛选按钮 点击table某一列的header内的搜索过滤图标,弹出的筛选弹框大致效果图如下所示:

首先来熟悉一下涉及到表格列筛选的属性api:
filterDropdown
:自定义筛选菜单filtered
:标识数据是否经过过滤,筛选状态时,column的header筛选图标会高亮filterIcon
:自定义filter图标filterMultiple
: 是否可以多选,默认为truefilterMode
: 指定筛选菜单的用户界面,可选’menu’或’tree’,默认’menu’filters
: 表头的筛选菜单项,这是实现筛选框多选的重要属性
自定义筛选菜单的实现
首先编写自定义筛选菜单,本文使用(props: FilterDropdownProps) => ReactNode
函数来定义filterDropdown
属性的值。代码如下: 首先定义接口,主要涉及到表头筛选菜单项类型ColumnFilterItem
、多选项类型CheckboxItem
和自定义筛选菜单传入的props的类型FilterDropdownProps
:
export interface ColumnFilterItem {text: string;value: string;children?: ColumnFilterItem[];
}
export interface CheckboxItem {label: string;value: string;
}
export interface FilterDropdownProps {setSelectedKeys: (selectedKeys: React.Key[]) => void;selectedKeys: React.Key[];confirm: (param?: any) => void;clearFilters?: () => void;filters: ColumnFilterItem[];
}
然后定义筛选菜单函数: 需要传入以下几个属性,他们分别表示的含义如下:
selectedKeys
:设置筛选时选中的value
,为数组setSelectedKeys
: 筛选值改变时调用的设置方法confirm
: 当点击确定按钮时调用此方法,能够使Table组件感应到,然后自动调用onFilter
属性对应的方法,comfirm
方法可以传入一个Object类型的参数,以便于控制回传的selectedKeys
和控制弹出框的关闭closeDropdown
clearFilters
: 该方法用于清空筛选,以便让Table组件感知到 首先定义方法:
const ColumnFilterSearch = ({setSelectedKeys,selectedKeys,confirm,clearFilters,filters,
}: FilterDropdownProps) => {}
然后在方法内部定义传入的菜单项值options
,菜单项需要格式化为label-value类型的对象:
// 初始多选项数据为传入的菜单项格式化后的值const options = filters?.map((item: ColumnFilterItem) => ({label: item.text,value: item.value,}));
定义方法中需要使用到的数据变量,包括全选状态变量checkAll
、全选状态效果变量indeterminate
和实时过滤后的菜单项filterOptions
,代码如下:
// 实现全选效果const [indeterminate, setIndeterminate] = useState(true);// 是否全选const [checkAll, setCheckAll] = useState(false);// 筛选后的所以数据项const [filterOptions, setFilterOptions] = useState(options);
实现全选按钮切换效果,全选状态改变时,需要使用map方法设置selectedKeys,并设置checkAll的值
// 全选按钮切换函数const onCheckAllChange = (e: any) => {setSelectedKeys(e.target.checked ? filterOptions.map((item: any) => item.value) : []);setIndeterminate(false);setCheckAll(e.target.checked);};
当我们通过多选不同的多选框选项时,需要实时改变选中的选项值和全选状态,代码如下:
// 选项改变时同时设置选中的值和是否满足全选const checkboxOnChange = (checkedValues: any) => {setSelectedKeys(checkedValues);setIndeterminate(!!checkedValues.length && checkedValues.length < filterOptions.length);setCheckAll(checkedValues.length === filterOptions.length);};
由于需要重置功能,即点击重置按钮,恢复取消全选状态、实现初始化时的效果,代码如下:
//重置时,设置选中的值为[],全选状态为false,同时调用clearFilters()函数实现清除筛选const handleReset = (clearFilters: () => void) => {clearFilters();setSelectedKeys([]);setCheckAll(false);};
因为可以通过头部的输入框进行筛选菜单项,为了提升输入体验,采用了防抖技术,等待输入完成后300ms后进行过滤:
// 实现输入过滤多选项,采用了防抖函数const handleInputChange = debounce((e: any) => {const filterOptions = options.filter((item: any) =>item.label.includes(e.target.value));setFilterOptions(filterOptions);},{ ms: 300 });
最后补上页面样式和结构的主要代码,主要使用到antd的组件、<Checkbox.Group />组件、组件和、组件:
return (<div classNames="wrap"><Inputplaceholder="搜索"prefix={<SearchIcon />}onChange={(e) => handleInputChange(e)}allowClearbordered={false}/><Checkbox.Groupoptions={filterOptions}value={selectedKeys}onChange={checkboxOnChange}></Checkbox.Group><div className="footer-btn"><Checkboxindeterminate={indeterminate}onChange={onCheckAllChange}checked={checkAll}>全选</Checkbox><Space><Buttonsize="small"type="primary"onClick={clearFilters && handleReset.bind(null, clearFilters)}>重置</Button><Buttonsize="small"type="primary"onClick={confirm.bind(null, { selectedKeys, closeDropdown: true })}>确定</Button></Space></div></div>);
其他筛选相关的属性配置
可以自定义column表头的筛选图标,通过filtered
参数实现切换筛选状态的样式:
filterIcon: (filtered: boolean) => (<SearchOutlined style={{ color: filtered ? '#eee' : undefined }} />),
最终确定筛选后实现表格列筛选的属性onFilter
,该属性对应的函数会循环遍历selectedKeys
,去依次执行每个筛选条件value和每行record,我们可以通过value和record实现最终的筛选功能。
onFilter: (value: string, record: any) => {console.log(value, record);return record.列的dataIndex.includes(value);},
以上代码有就实现了依据table某列数据去筛选表格数据。
最后
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取