React+hook实现联动模糊搜索
作者:某哈压力大
这篇文章主要为大家详细介绍了如何利用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>
部分关键业务逻辑代码实现
// 当用户选中某一机构时 centerHandleOrgChangeHandle = async (v) => { // 先置空处理人栏位 this.formRef.current.setFieldsValue({ centerHandleUser: "", }) if(!v){ return } // 获取有权用户列表(非全量) const data = {centerHandleOrg: v}; const {list = []} = await getOrgUserList(data); this.debounceSelectRef.current.update(reNameObj(list)); } // 当用户输入关键字进行检索有权用户时 // 在子组件中会触发onSearch => 触发fetchUserList fetchUserList = async (data) => { return new Promise(resolve => { const data = {centerHandleOrg: v}; const {list = []} = await getOrgUserList(data); resolve(reNameObj(list)); // 向子中注入新的options,查询数据完成 }) }
部分使用到的方法代码实现如下
// 由于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; }
部分效果预览
搜索中:
总结
使用防抖减少接口频繁调用
使用缓存减少性能消耗
使用数据备份这种方式提示用户体验。
到此这篇关于React+hook实现联动模糊搜索的文章就介绍到这了,更多相关React模糊搜索内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!