React+hook實(shí)現(xiàn)聯(lián)動模糊搜索
背景
需要從用戶選中的機(jī)構(gòu)中,聯(lián)動加載相對應(yīng)的有權(quán)處理人。
由于有權(quán)處理人數(shù)據(jù)量較大,并且需要動態(tài)加載,無法將所有枚舉都放在前端靜態(tài)資源中。
需要根據(jù)所選擇的機(jī)構(gòu),默認(rèn)加載一部分的處理人,剩下的,根據(jù)用戶手輸?shù)臄?shù)據(jù),與后臺交互,模糊匹配對應(yīng)的選項(xiàng)。
實(shí)現(xiàn)思路
- 使用React + hook + antd
- 需要對搜索框進(jìn)行防抖處理,避免性能浪費(fèi)
- 用戶清除搜索條件時,應(yīng)該將枚舉列表恢復(fù)為上一狀態(tài)。
主要代碼實(shí)現(xiàn)
DebounceSelect:動態(tài)加載的下拉框
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:用戶輸入的關(guān)鍵字
const loadOptions = (keyWord) => {
if(!keyWord) return
setOptions([]);
setFetching(true);
// 同時觸發(fā)父組件的fetchUserList,并傳入?yún)?shù)
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}
/>
)
})
父組件中機(jī)構(gòu)和處理人的部分靜態(tài)代碼實(shí)現(xiàn)
// ...相關(guān)依賴引入
<Row>
<Col span={11}>
<Form.Item label="處理機(jī)構(gòu)" 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="請輸入進(jìn)行查找"
fetchOption={this.fetchUserList}
/>
</Form.Item>
</Col>
</Row>
部分關(guān)鍵業(yè)務(wù)邏輯代碼實(shí)現(xiàn)
// 當(dāng)用戶選中某一機(jī)構(gòu)時
centerHandleOrgChangeHandle = async (v) => {
// 先置空處理人欄位
this.formRef.current.setFieldsValue({
centerHandleUser: "",
})
if(!v){
return
}
// 獲取有權(quán)用戶列表(非全量)
const data = {centerHandleOrg: v};
const {list = []} = await getOrgUserList(data);
this.debounceSelectRef.current.update(reNameObj(list));
}
// 當(dāng)用戶輸入關(guān)鍵字進(jìn)行檢索有權(quán)用戶時
// 在子組件中會觸發(fā)onSearch => 觸發(fā)fetchUserList
fetchUserList = async (data) => {
return new Promise(resolve => {
const data = {centerHandleOrg: v};
const {list = []} = await getOrgUserList(data);
resolve(reNameObj(list)); // 向子中注入新的options,查詢數(shù)據(jù)完成
})
}
部分使用到的方法代碼實(shí)現(xiàn)如下
// 由于select是默認(rèn)按照label,value做鍵的
const reNameObj = (list) =>
list.map(({userName, userCode, ...rest}) => ({
label: `${userCode}-${userName},`
value: userCode,
...rest,
}))
// 前端進(jìn)行模糊匹配的時候,如果返顯的下拉選項(xiàng)為拼接后的話,會被拆成一個數(shù)組,無法直接匹配
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;
}
部分效果預(yù)覽
搜索中:

總結(jié)
使用防抖減少接口頻繁調(diào)用
使用緩存減少性能消耗
使用數(shù)據(jù)備份這種方式提示用戶體驗(yàn)。
到此這篇關(guān)于React+hook實(shí)現(xiàn)聯(lián)動模糊搜索的文章就介紹到這了,更多相關(guān)React模糊搜索內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React項(xiàng)目打包發(fā)布到Tomcat頁面空白問題及解決
這篇文章主要介紹了React項(xiàng)目打包發(fā)布到Tomcat頁面空白問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-06-06
React實(shí)現(xiàn)二級聯(lián)動效果(樓梯效果)
這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)二級聯(lián)動效果,樓梯效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
Next.js搭建Monorepo組件庫文檔實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Next.js搭建Monorepo組件庫文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
React引入css的幾種方式及應(yīng)用小結(jié)
這篇文章主要介紹了React引入css的幾種方式及應(yīng)用小結(jié),操作styled組件的樣式屬性,可在組件標(biāo)簽上定義屬性、也可以通過attrs定義屬性,本文通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03

