jiefancis / blogs

个人博客,学习笔记(issues)
1 stars 0 forks source link

记一次antd select组件过滤功能的深入了解 #25

Open jiefancis opened 2 years ago

jiefancis commented 2 years ago

背景

最近做的需求, 其中有一个需求是将国家下拉多选框的内容分组展示, 分组后在选择数据的过程中,发现数据太多,而我只想勾选一个国家,所以我想着输入要选择的国家名过滤出来勾选即可并且ui组件库的下拉框都有实现过滤筛选的功能,于是我也这么去做了,结果发现筛选不出来...当我使用国家组名筛选时可以筛选出这个组及组内国家的数据.但是呢,有些国家我不知道都有哪些组及要筛选的国家是属于哪个组,我还是得一个一个的去找,很麻烦,于是我在想,能不能在分组的情况下还能跟未分组一样过滤呢?

问题

select分组后如何支持数据过滤(跟未分组一样的效果)

确定antd版本

在查看源码前,我查看了github上antd的分支,发现antd的分支中有各个大版本的稳定版及master分支是4.x版本,为了更好的定位问题我查看了项目中使用的antd版本,确定好大版本后,到github找到对应的下载源码.
当然你也可以通过打开codespaces的方式在将github上的代码在本地vscode上打开.或者也可以在github上打开打开网页版的vscode

查看antd select源码

直接查看select源码
在查看select源码前,我猜想select模糊搜索的实现方式: 拿到input输入数据后,对options中数据的label进行filter过滤,找到满足条件的数据数组.按照这个思路,我去查看select源码,发现很多代码看的头疼,而且也不知道在做什么,所以我打算换个方式:

查找input change方法
根据select实现的猜想,我只要找到select组件中input输入框子元素的onchange方法,由这个方法去反推向上查找select的是实现...这个方式也不行...

查找displayOptions来源
发现select筛选后数据是在列表展示,所以我能不能通过找到下拉列表中的数据的来源去向上查找,最终找到了hooks/useOptions 文件,这个hook中对options和children的数据进行规范化处理,Select.Option组件在这里被转换为options的格式,在这过程中涉及到options与Select.Option同时使用的优先级问题

options与Select.Option优先级
options和Select.Option标签一起使用时,options的优先级高于Select.Option.下面代码表示当options不存在时,取children数据作为options选项.

@filename(hooks/useOptions.tsx)

let mergedOptions = options;
const childrenAsData = !options;

if (childrenAsData) {
    mergedOptions = convertChildrenToData(children);
}

Select.Option + Select.OptGroup转换为options数组的数据格式
convertChildrenToData(children)方法将Select.Option + Select.OptGroup转换为options数组的数据格式,如下所示,为了验证数据转换成options属性后是否能正确展示,因此我到codesanbox创建了一个例子, 放开options select展示的数据以options优先. 放开optionFilterProp="children",能正常对数据进行过滤,否则只能对组名进行模糊搜索

{
    label,
    key,
    options: [
        {
            children,
            value,
            key
        }
    ]
}

例子

本篇文章的代码在codesandbox

延伸

compositionStart与compositionEnd