React+hook實(shí)現(xiàn)聯(lián)動(dòng)模糊搜索
背景
需要從用戶選中的機(jī)構(gòu)中,聯(lián)動(dòng)加載相對(duì)應(yīng)的有權(quán)處理人。
由于有權(quán)處理人數(shù)據(jù)量較大,并且需要?jiǎng)討B(tài)加載,無法將所有枚舉都放在前端靜態(tài)資源中。
需要根據(jù)所選擇的機(jī)構(gòu),默認(rèn)加載一部分的處理人,剩下的,根據(jù)用戶手輸?shù)臄?shù)據(jù),與后臺(tái)交互,模糊匹配對(duì)應(yīng)的選項(xiàng)。
實(shí)現(xiàn)思路
- 使用React + hook + antd
- 需要對(duì)搜索框進(jìn)行防抖處理,避免性能浪費(fèi)
- 用戶清除搜索條件時(shí),應(yīng)該將枚舉列表恢復(fù)為上一狀態(tài)。
主要代碼實(shí)現(xiàn)
DebounceSelect:動(dòng)態(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); // 同時(shí)觸發(fā)父組件的fetchUserList,并傳入?yún)?shù) fetchOptions({centerHandleOrg, keyWord}).then(newOptions => { setOptions(newOptions); setFetching(false) }) } return debounce(loadOptions, debounceTimeout); },[ centerHandleOrg, fetchOptions, debounceTimeout]) // 向父組件拋出對(duì)象 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="請(qǐng)輸入進(jìn)行查找" fetchOption={this.fetchUserList} /> </Form.Item> </Col> </Row>
部分關(guān)鍵業(yè)務(wù)邏輯代碼實(shí)現(xiàn)
// 當(dāng)用戶選中某一機(jī)構(gòu)時(shí) 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)用戶時(shí) // 在子組件中會(huì)觸發(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)行模糊匹配的時(shí)候,如果返顯的下拉選項(xiàng)為拼接后的話,會(huì)被拆成一個(gè)數(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)動(dòng)模糊搜索的文章就介紹到這了,更多相關(guān)React模糊搜索內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React項(xiàng)目打包發(fā)布到Tomcat頁面空白問題及解決
這篇文章主要介紹了React項(xiàng)目打包發(fā)布到Tomcat頁面空白問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06React實(shí)現(xiàn)二級(jí)聯(lián)動(dòng)效果(樓梯效果)
這篇文章主要為大家詳細(xì)介紹了React實(shí)現(xiàn)二級(jí)聯(lián)動(dòng)效果,樓梯效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09Next.js搭建Monorepo組件庫文檔實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Next.js搭建Monorepo組件庫文檔,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11React引入css的幾種方式及應(yīng)用小結(jié)
這篇文章主要介紹了React引入css的幾種方式及應(yīng)用小結(jié),操作styled組件的樣式屬性,可在組件標(biāo)簽上定義屬性、也可以通過attrs定義屬性,本文通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-03-03