【React-admin】构建React应用(14)- 基于ant.design扩展select过滤

在使用antdselect组件的时候,由于对lable扩展或者lable的复杂化,那么在展示的时候可能有很多lable是一样的,在选择的时候无法区分。所以需要根据属性对options进行过滤。

比如封装后的组件是下图这样的,那么这每一个option将会是很复杂的。用户在使用的时候可能只记住某一个属性,并且需要根据这个属性进行筛选。比如服务对象,包含服务和端口号,我需要根据协议进行过滤。
在这里插入图片描述
那么就需要对select组件进行扩展,首先分析一下,如果你需要根据属性进行过滤,那么这个option上需要封装相关的属性。我们知道select中的定义基本是:

{
	lable:''
	value:''
}

除此之外,因为它本身也是个对象,可以额外添加我们需要的字段属性,比如下图所示,我需要支持hostname,uuid,ip地址过滤,所以在option中附件了额外的信息:
在这里插入图片描述
我们知道在配置页面的下拉数据,一般都是从后台拉取过来的,所以请求回来数据后,重新封装一下就可以了。数据封装完了,可以在官网看到这么个例子检索用户数据

里面给出了动态的向服务端请求数据,但是为了减少服务器的压力,我会在页面加载列表的时候把需要的数据准备好,因为可能在添加/修改页面都会用到。

数据准备好就可以参考官网给出的列子进行coding了。

别着急动手,在codig之前我们还需要解决一个问题:怎么支持用户根据不同的属性进行过滤呢?

最初的设计是:在提供选择框的同时,给定用户一个选择属性的功能,然后获取到属性和搜索值,记进行匹配。但是想想似乎不太合理,一来页面布局会显得臃肿,二来你需要考虑属性配置的问题,搞起来有点麻烦

记得当初使用wireshark的时候,曾经使用过根据ip过滤的操作,便想到,其实我们也可以参考这种方式即在select中输入数据各格式为:属性=值,即ip=xx.x.x.x的格式。然后对格式进行处理就可以获取到属性和值

如果你使用过qslodash,那么看到这里,你回很开心。

  • qs:可以帮你处理路径参数问题,形如:ip=xx.x.x.x通过qs.parse(ip=xx.x.x.x),可以自转换为{ip:xx.x.x.x}的格式
  • lodash:lodash的filter方法可以根据一个对象去匹配,也就是可以通过{ip:xx.x.x.x}去一个包含ip属性的对象数据中匹配到一致的数据。
    在这里插入图片描述
  • 除此之外你似乎还要考虑防抖的问题,但是在antd中他已经给你做好了,你就不需要处理了。但是一个敏感的前端程序员,应该会想到这个频繁触发导致频繁渲染或者请求的东西,都需要做防抖和节流处理。至于是防抖还是节流,需要你根据业务来判断了。

那么知道这些,我们就可以动手封装这个组件了:

import React, { useState, useMemo } from 'react'
import { Select, Spin } from 'antd';
import { debounce, filter } from 'lodash';
import qs from 'qs'

/**
 * 该组件支持属根据属性查询,格式为:属性=值,如ip=xx.x.x.x
 * @param {*} props 
 * @returns 
 */
export default function DebounceSelect(props) {
  const { fetchOptions } = props
  const [fetching, setFetching] = useState(false);
  const [options, setOptions] = useState(fetchOptions);
  const debounceFetcher = useMemo(() => {
    const loadOptions = (query) => {
      if (!query) {
        setOptions(fetchOptions);
      } else {
        console.log("查询字符串:", query)
        // 将查询数据进行解析
        const obj = qs.parse(query)
        console.log("解析结果:", obj)
        // 根据解析后的数据记进行匹配
        const newOptions = filter(fetchOptions, obj)
        console.log("匹配到的数据:", newOptions)
        setOptions(newOptions);
        setFetching(false);
      }
    };
    return debounce(loadOptions, 1000);
  }, [fetchOptions]);

  /**
   * 根据属性去过滤
   * @param {*} options 需要过滤的数据
   * @param {*} attrs 根据哪些属性去过滤
   */
  return (
    <Select
      mode="multiple"
      optionLabelProp="name"
      showSearch
      filterOption={false}
      onSearch={debounceFetcher}
      notFoundContent={fetching ? <Spin size="small" /> : null}
      {...props}
      options={options}
    />
  );
}

将该组件导入大到其他组件中使用

<DebounceSelect
	value={workload}
	onChange={newValue => {
	changeW(newValue);
	}}
	fetchOptions={workloadsT} 
/>

当输入这种格式的搜索数据时,就会输出正确的结果。
在这里插入图片描述
如果你是自己写的,那么可能会出现匹配到数据时,options跟新了,但是没有正确渲染到select中,那么你可以少了一个属性:filterOption={false}。否则他会根据输入项筛选,因为它默认值是true,会根据ip=xx.x.x.x的格式去过滤,它默认的是从label中过滤
在这里插入图片描述


版权声明:本文为chenqk_123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>