search-select

实例

Example1 - 远程搜索

import React, { useState, useRef, useMemo, ReactNode } from "react";
import ReactDOM from "react-dom";
import debounce from "lodash/debounce";
import { Select, Spin } from "antd";
import { SelectProps } from "antd/es/select";import "antd/dist/antd.css";
import "./index.css";export interface SearchSelectProps<ValueType = any>extends Omit<SelectProps<ValueType>, "options" | "children"> {fetchOptions: (search: string) => Promise<ValueType[]>;debounceTimeout?: number;
}function SearchSelect<ValueType extends {key?: string;label: ReactNode;value: string | number;} = any
>({ fetchOptions, debounceTimeout = 800, ...props }: SearchSelectProps) {const [fetching, setFetching] = useState(false);const [options, setOptions] = useState<ValueType[]>([]);const fetchRef = useRef(0);const searchFetcher = useMemo(() => {const loadOptions = (value: string) => {fetchRef.current += 1;const fetchId = fetchRef.current;setOptions([]);setFetching(true);fetchOptions(value).then((newOptions) => {if (fetchId !== fetchRef.current) {// for fetch callbacl orderreturn;}setOptions(newOptions);setFetching(false);});};return debounce(loadOptions, debounceTimeout);}, [fetchOptions, debounceTimeout]);return (<Select<ValueType>showSearchlabelInValuefilterOption={false}onSearch={searchFetcher}notFoundContent={fetching ? <Spin size="small" /> : null}{...props}options={options}/>);
}// Usage of searchSelect
interface searchSelectUserValue {label: string;value: string;
}async function fetchUserList(username: string
): Promise<searchSelectUserValue[]> {console.log("fetching user", username);// 本地mockreturn new Promise((resolve, reject) => {const response = [{ label: "张三", value: "zhansan" },{ label: "李四", value: "lisi" },{ label: "王五", value: "wangwu" }];resolve(response);});// return fetch('url').then((res) => {});
}const SearchSelectDemo = () => {const [value, setValue] = useState<searchSelectUserValue[]>([]);return (<div><SearchSelectclassName="search-select"mode="multiple"value={value}placeholder="请输入搜索条件"fetchOptions={fetchUserList}onChange={(newValue) => {setValue(newValue);}}/></div>);
};ReactDOM.render(<SearchSelectDemo />, document.getElementById("root"));

Example2 - 本地搜索

import React, { useState, useRef, useMemo, ReactNode } from "react";
import ReactDOM from "react-dom";
import debounce from "lodash/debounce";
import { Select, Spin } from "antd";
import { SelectProps } from "antd/es/select";import "antd/dist/antd.css";
import "./index.css";export interface SearchSelectProps<ValueType = any>extends Omit<SelectProps<ValueType>, "options" | "children"> {fetchOptions: (search: string) => Promise<ValueType[]>;debounceTimeout?: number;
}function SearchSelect<ValueType extends {key?: string;label: ReactNode;value: string | number;} = any
>({ fetchOptions, debounceTimeout = 800, ...props }: SearchSelectProps) {const [fetching, setFetching] = useState(false);const [options, setOptions] = useState<ValueType[]>([]);const fetchRef = useRef(0);const searchFetcher = useMemo(() => {const loadOptions = (value: string) => {fetchRef.current += 1;const fetchId = fetchRef.current;setOptions([]);setFetching(true);fetchOptions(value).then((newOptions) => {if (fetchId !== fetchRef.current) {// for fetch callbacl orderreturn;}setOptions(newOptions);setFetching(false);});};return debounce(loadOptions, debounceTimeout);}, [fetchOptions, debounceTimeout]);return (<Select<ValueType>showSearchlabelInValuefilterOption={true}onSearch={searchFetcher}notFoundContent={fetching ? <Spin size="small" /> : null}{...props}options={options}/>);
}// Usage of searchSelect
interface searchSelectUserValue {label: string;value: string;
}async function fetchUserList(username: string
): Promise<searchSelectUserValue[]> {console.log("fetching user", username);// 本地mockreturn new Promise((resolve, reject) => {const response = [{ label: "张三", value: "zhansan" },{ label: "李四", value: "lisi" },{ label: "王五", value: "wangwu" }];resolve(response);});// return fetch('url').then((res) => {});
}const SearchSelectDemo = () => {const [value, setValue] = useState<searchSelectUserValue[]>([]);return (<div><SearchSelectclassName="search-select"mode="multiple"value={value}placeholder="请输入搜索条件"fetchOptions={fetchUserList}onChange={(newValue) => {setValue(newValue);}}/></div>);
};ReactDOM.render(<SearchSelectDemo />, document.getElementById("root"))

参数说明

参数 说明 类型 默认值 版本
filterOption 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false boolean | function(inputValue, option) true
labeInValue 是否把每个选项的label包装到value中,会把Select的value类型从string变为{value: string, label: ReactNode}的格式 boolean false -

源码分析

  • ant-design 使用的是rc-select去作为基本的组件,filterOption的解析是获取之后走到了rc-select之中了。
// 源码位置 https://github.com/react-component/select/blob/13.x/src/utils/valueUtil.ts
/** Filter single option if match the search text */function getFilterFunction(optionFilterProp) {return function (searchValue, option) {var lowerSearchText = searchValue.toLowerCase(); // Group label searchif ('options' in option) {return toRawString(option.label).toLowerCase().includes(lowerSearchText);} // Option value searchvar rawValue = option[optionFilterProp];var value = toRawString(rawValue).toLowerCase();return value.includes(lowerSearchText);};
}function filterOptions(searchValue, options, _ref6) {var optionFilterProp = _ref6.optionFilterProp,filterOption = _ref6.filterOption;var filteredOptions = [];var filterFunc;if (filterOption === false) {return (0, _toConsumableArray2.default)(options);}if (typeof filterOption === 'function') {filterFunc = filterOption;} else {filterFunc = getFilterFunction(optionFilterProp);}options.forEach(function (item) {// Group should check child optionsif ('options' in item) {// Check group firstvar matchGroup = filterFunc(searchValue, item);if (matchGroup) {filteredOptions.push(item);} else {// Check optionvar subOptions = item.options.filter(function (subItem) {return filterFunc(searchValue, subItem);});if (subOptions.length) {filteredOptions.push((0, _objectSpread2.default)((0, _objectSpread2.default)({}, item), {}, {options: subOptions}));}}return;}if (filterFunc(searchValue, injectPropsWithOption(item))) {filteredOptions.push(item);}});return filteredOptions;
}
  • 为什么会去处理filterOptions了?因为进入的时候做了一步generate操作,也就是rc-select SelectProps是generate中 import type { SelectProps, RefSelectProps } from './generate';
// https://github.com/react-component/select/blob/13.x/src/generate.tsx// Display options for OptionListconst displayOptions = useMemo<OptionsType>(() => {if (!mergedSearchValue || !mergedShowSearch) {return [...mergedOptions] as OptionsType;}const filteredOptions: OptionsType = filterOptions(mergedSearchValue, mergedOptions, {optionFilterProp,filterOption: mode === 'combobox' && filterOption === undefined ? () => true : filterOption,});if (mode === 'tags' &&filteredOptions.every((opt) => opt[optionFilterProp] !== mergedSearchValue)) {filteredOptions.unshift({value: mergedSearchValue,label: mergedSearchValue,key: '__RC_SELECT_TAG_PLACEHOLDER__',});}if (filterSort && Array.isArray(filteredOptions)) {return ([...filteredOptions] as OptionsType).sort(filterSort);}return filteredOptions;}, [mergedOptions, mergedSearchValue, mode, mergedShowSearch, filterSort]);const popupNode = (<OptionList{...}options={displayOptions}{...}/>);
// vsvar displayOptions = (0, React.useMemo)(function () {if (!mergedSearchValue || !mergedShowSearch) {return (0, _toConsumableArray2.default)(mergedOptions);}var filteredOptions = filterOptions(mergedSearchValue, mergedOptions, {optionFilterProp: optionFilterProp,filterOption: mode === 'combobox' && filterOption === undefined ? function () {return true;} : filterOption});if (mode === 'tags' && filteredOptions.every(function (opt) {return opt[optionFilterProp] !== mergedSearchValue;})) {filteredOptions.unshift({value: mergedSearchValue,label: mergedSearchValue,key: '__RC_SELECT_TAG_PLACEHOLDER__'});}if (filterSort && Array.isArray(filteredOptions)) {return (0, _toConsumableArray2.default)(filteredOptions).sort(filterSort);}return filteredOptions;}, [mergedOptions, mergedSearchValue, mode, mergedShowSearch, filterSort]);var popupNode = /*#__PURE__*/React.createElement(OptionList, {{...}options: displayOptions,{...}}); // ============================= Clear ==============================
  • filterOption: mode === 'combobox' && filterOption === undefined ?function () { return true; } : filterOption 这段代码也就说明了如果我不设置filterOption的话,它默认是true的缘由。

Thinking in JackDan

antd系列之Select相关推荐

  1. Antd点击select选择框,页面滚动,选项跟着滚动

    遇到问题如下: 做项目时,采用antd与react技术方案,需要实现选择一个select选择框,发现点击select选择框时,滚动页面,选项内容整体跟着页面滚动,而select选择框不动,如图: 解决 ...

  2. Linux命令:MySQL系列之五--SELECT单表查询、多表查询升级及删除,插入

    SELECT:查询 SELECT select-list FROM tb WHERE qualification  根据标准qualification查找对应的行 查询语句类型:  qualifica ...

  3. elementui下拉框选择图片_Element UI系列:Select下拉框实现默认选择

    [编程题目]一个整数数组,长度为 n,将其分为 m 份,使各份的和相等,求 m 的最大值★★ (自己没有做出来!!) 45.雅虎(运算.矩阵): 2.一个整数数组,长度为 n,将其分为 m 份,使各份 ...

  4. 支持大数据渲染下拉列表组件开发 SuperSelect(基于antd Select)

    功能简介 antd 的 Select 组件不支持大数据量的下拉列表渲染,下拉列表数量太多会出现性能问题, SuperSelect 基于 antd 封装实现,替换原组件下拉列表,只渲染几十条列表数据,随 ...

  5. antd checkbox 默认选中_antd + select 默认选中问题?

    题目描述 react + antd select 默认选中问题 题目来源及自己的思路 我是通过 const { getFieldDecorator } = this.props.form;来设置他们的 ...

  6. antd vue 多个下拉 联动_antd中select下拉框值为对象选中的问题

    使用antd中的select下拉框,遇到个小问题,后台管理系统中,使用下拉框,一般不会是简单的就直接使用select中的value值,而是会使用id或者value中文对应的keyword,并且这个在o ...

  7. React全家桶+AntD 实战二

    React全家桶+AntD 单车后台管理系统开发(完整版) (第8章 单车业务之城市管理模块&) 第8章 单车业务之城市管理模块& src/router.js,通用路由 import ...

  8. 【MySQL性能优化系列】百万数据limit分页优化

    背景 众所周知,在使用limit分页过程中,随着前端传过来的PageSize越来越大,查询速度会越来越慢.那有什么优化的办法呢? 本文将通过百万数据表进行演示和优化, 欲知详情,请看下文分解. lim ...

  9. antd protable

    具体参数查看官方文档:ProTable - 高级表格 - ProComponents 想要实现外部传递进来的参数,每次参数变化,重新请求接口 useEffect(async () => {if ...

  10. mysql系列 -查询

    1. 准备 查看表的创建语句: show create table [表名] create table goods (goods_id mediumint(8) unsigned primary ke ...

最新文章

  1. 最小生成树(kruskal、prim、最小生成森林问题、严格次小生成树)
  2. SharedPreferences源码解析
  3. hadoop 9000端口的服务未启动_IDEA 微服务单项目多端口启动
  4. 灯光工厂滤镜插件knoll light factory
  5. 布隆过滤器Redis缓存穿透雪崩击穿热点key
  6. python -v乱码提示,#import....等信息的问题解决方式。
  7. oracle 查看锁死的表
  8. 一文带你掌握OBS的两种常见的鉴权方式
  9. 宝塔Linux面板公司,宝塔面板_宝塔Linux面板-九州数码,一站式云安全服务平台
  10. Android 音视频深入 十四 FFmpeg与OpenSL ES 播放mp3音乐,能暂停(附源码
  11. idea 安装热部署插件
  12. c语言串口接收的字符转int,从串口发送和接收int值
  13. 电脑怎么设置扬声器播放麦克风的声音
  14. 解析TCP/UDP协议的通讯软件
  15. C网跟G网是什么意思?
  16. bzoj1627 / P2873 [USACO07DEC]泥水坑Mud Puddles
  17. DolphinScheduler 3.0.0-alpha 安装问题
  18. (在WPS或者WORD中使用MathType编辑数学公式)写论文必备
  19. Cadence学习记录(三)芯片封装设计
  20. macbook 备份系统

热门文章

  1. html 转盘素材,jQuery指针不动转盘动的Rotate转盘插件
  2. 贝尔宾团队角色理论及实践
  3. 淘宝上大量贩卖微信号,这些人买这么多微信号目的是
  4. Springboot中Aspect实现切面(以记录日志为例)
  5. python中oct函数_Python中的oct() 函数是什么?
  6. 运维审计系统是堡垒机么?跟堡垒机有啥区别?
  7. 爬虫爬取wallpaperswide上的高清壁纸
  8. H.264之几种开源解码器的对比评测
  9. 头条小程序对接微信、支付宝
  10. 我的007之skyfall歌词鉴赏及翻译