今天我们来聊聊使用 React + hook + antd 实现联动模糊搜索。
需要从用户选中的机构中,联动加载相对应的有权处理人。
由于有权处理人数据量较大,并且需要动态加载,无法将所有枚举都放在前端静态资源中。
需要根据所选择的机构,默认加载一部分的处理人,剩下的,根据用户手输的数据,与后台交互,模糊匹配对应的选项。
实现思路
使用React + hook + antd
需要对搜索框进行防抖处理,避免性能浪费
用户清除搜索条件时,应该将枚举列表恢复为上一状态。
主要代码实现
DebounceSelect:动态加载的下拉框
import React, { forwardRef, useImperativeHandle, useState, useMemo } from 'react'; import { Select, Spin } from "antd"; import debounce from "lodash/debounce"; export const DebounceSelect = forwardRef(({ fetchOptions, debounceTimeout = 800, ...props}, ref) => { const [fetching, setFetching] = useState(false); const [options, setOptions] = useState([]); const [userListBackUp, setUserListBackUp] = useSate([]); const [centerHandleOrg, setCenterHandleOrg] = useState(""); const debounceFetcher = useMemo(() => { // keyWord:用户输入的关键字 const loadOptions = (keyWord) => { if(!keyWord) return setOptions([]); setFetching(true); // 同时触发父组件的fetchUserList,并传入参数 fetchOptions({centerHandleOrg, keyWord}).then(newOptions => { setOptions(newOptions); setFetching(false) }) } return debounce(loadOptions, debounceTimeout); },[ centerHandleOrg, fetchOptions, debounceTimeout]) // 向父组件抛出对象 useImperativeHandle(ref, () => ({ update: (list = [], _centerHandleOrg = "") => { setOptions(list); setUserListBackUp(list); setCenterHandleOrg(_centerHandleOrg); } })); return( <Select allowClear showSearch filterOption={false} onSearch={debounceFetcher} onClear={() => setOptions(userListBackUp)} notFoundContent={fetching ? <Spin size="small"/> : null} {...props} options={options} /> ) })
父组件中机构和处理人的部分静态代码实现
// ...相关依赖引入 <Row> <Col span={11}> <Form.Item label="处理机构" name="centerHandleOrg"> <Select allowClear showSearch filterOption={(val, option) => selectFilterIsBool(val, option)} onSelect={this.centerHandleOrgChangeHandle} onClear={() => this.debounceSelectRef.current.update()}> {this.state.centerHandleOrgList.map(item => ( <Option key={item.orgCode} value={item.orgCode}> {item.orgCode}-{item.orgName} </Option> ))} </Select> </Form.Item> </Col> <Col span={11}> <Form.Item label="处理人" name="centerHandleUser"> <DebounceSelect ref={this.debounceSelectRef} placeholder="请输入进行查找" fetchOption={this.fetchUserList} /> </Form.Item> </Col> </Row>
部分使用到的方法代码实现如下
// 由于select是默认按照label,value做键的 const reNameObj = (list) => list.map(({userName, userCode, ...rest}) => ({ label: `${userCode}-${userName},` value: userCode, ...rest, })) // 前端进行模糊匹配的时候,如果返显的下拉选项为拼接后的话,会被拆成一个数组,无法直接匹配 const selectFilterIsBool = (val = "", option = "") => { if(option.props.children){ if(Objec.prototype.toString.call(option.props.children) !== "[object Array]"){ return option.props.children.includes(val); } return option.props.children.join("").includes(val); } return false; }
部分效果预览
搜索中:
总结
使用防抖减少接口频繁调用
使用缓存减少性能消耗
使用数据备份这种方式提示用户体验。
网友评论文明上网理性发言 已有0人参与
发表评论: