antd 中对树形表格中二级元素进行筛选过滤

今天做了一个 antd 的表格,该表格是个树形表格,也就是一行中还有 children 元素作为子行。

如图所示:

需求要求对二级元素即 children 元素进行筛选,但是 antd 自身的 onFilter 并不能筛选 children。。。我也在网上查询了相关信息,并没查到有效的解决方案,相对有效的就是筛选的时候自己对 dataSource 进行过滤,但是这就会导致复杂度的增加。比如此方案我们就需要将后端返回的数据克隆一份,然后对此克隆数据进行过滤等操作。而且我这需求中还需要对后端返回的数据进行编辑,编辑的文件也是备份文件,那么编辑后还要将备份文件和源文件同步等操作。这就很蛋疼了。。。

不过最后还是通过一个比较简单的方法解决了此问题。
在对 dataSource 不进行删除就实现过滤功能,首先想到的就是如何能隐藏某一行,比如可以给 dataSource 中的每行添加一个 hidden 属性,通过判断此属性来决定这行是否显示。
在查询 antd 的文档后,终于发现了此方法,这样的功能可能比较少见,网上也没有能直接搜到的结果,其实就是通过设置 onRow 属性:

<Table
    columns={departmentColumns}
    dataSource={dataSource}
    loading={loading}
    expandIconColumnIndex={1}
    pagination={false}
    onRow={record => {
        // 隐藏 hidden 为 true 的行
        if (record.hidden) {
            return {
                style: { display: 'none' }
            }
        }
    }}
/>

这个属性我之前也没用到过,而且文档中也只举例了几个事件绑定操作,我也是通过观察猜测实验后得出的方法:)
既然能隐藏某一行那就好说了,只需在进行筛选的时候先将所有元素先显示即 hidden: true,再在 onFilter 里对被过滤的元素隐藏即可。

    const [filterValue, setFilterValue] = useState({ first: '', firstScore: '', second: '', secondScore: '' });
    const onFilterChange = (type, v) => {
        // 每次过滤的时候,都先将所有行的 hidden 改为 false
        // 这里将所有改为 false,不用担心其它某列进行了筛选,把为 true 的给改到了。因为 antd 的 columns 中的 onFilter 会在每次重新渲染的时候都执行一遍
        dataSource.forEach(item => {
            item.hidden = false;
            item.children.forEach(child => {
                child.hidden = false;
            });
        })

        setFilterValue({
            ...filterValue,
            [type]: v
        });
    }
        {
            title: '得分【状态】',
            dataIndex: 'secondScore',
            filterDropdown: <FilterRadio
                options={secondScoreLevelFilter}
                value={filterValue.secondScore}
                onChange={v => {
                    onFilterChange('secondScore', v);
                }}
            />,
            filteredValue: filterValue.secondScore ? [filterValue.secondScore] : null,
            onFilter: (v, record) => {
                // 二级过滤,只能通过给行添加 hidden: true,然后通过 Table 的 onRow 进行过滤
                record.children.forEach(child => {
                    child.hidden = child.hidden || child.scoreLvl !== v;  // 需要先判断下如果当前行 hidden 为 true 就直接返回。hidden 为 true 说明其它列的筛选将此行过滤了。
                });
                return record.children.find(item => item.scoreLvl === v);
            },
            render(v, record) {
                return record.index ? null :`${getValue(record.score)}【${getValue(record.scoreLvl)}】`;
            }
        },

希望这篇文章能帮到遇到类似需求的同行~

原文地址:https://www.cnblogs.com/3body/p/14318068.html