这个需求看着简单,但是实现起来走了不少弯路。
![在这里插入图片描述](https://img-blog.csdnimg.cn/74008ea8204c47e5b33ada2e82c56e26.png
1. 需求
- 当输入关键词时,远程搜索内容,有返回则下拉展示,无返回也要展示当前输入的关键词(不能失去焦点后输入框就置空了),然后点击查询就会根据输入框中的值查询公司的相关信息,也就是会调用两个接口
- 要支持防抖搜索
这里面就遇到了几个问题:
- 远程搜索的时候,有数据返回,但是下拉展示的仍然是无数据。。。
- 搜索输入框正常情况下只支持下拉选中,如果输入的内容查不到,那么在失去焦点的时候就置空输入框了,也就是没法保持输入内容。
2.解决
- 问题1是因为select默认对搜索内容进行了过滤,可以设置
filterOption
为false
,filterOption
是会过滤数据,当返回值包含输入值才会显示在下拉框中。 - 问题2就需要多个步骤去解决了,1是设置
select
的value
,2是在搜索和失去焦点的时候再次set
value,保证输入框不置空。
3.代码
import { Button, Form, Input, message, Select } from 'antd'
import { useState, useEffect } from 'react'
import { useForm } from 'antd/es/form/Form'
import pageService from './service'
const AddModal = (props) => {
const [form] = useForm()
const [loadingCompay, setLoadingCompay] = useState(false) //查询公司名
const [loadingUnicode, setLoadingUnicode] = useState(false) //查询统一信用代码
const [companyList, setCompanyList] = useState([]) //模糊企业搜索下拉
const [keyword, setKeyword] = useState('') //模糊关键词
// 防抖
const debounce = (fn, delay = 1000) => {
let timer: any = null
// 闭包
return function f(args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
timer = null
fn.call(this, args)
}, delay)
}
}
// 模糊搜索
const getCompany = async (e) => {
if (!e) {
return false
}
let params = {
keyword: e,
}
let res = await pageService.getCompany(params)
if (res?.msgCode === '000000') {
setCompanyList(res.data || [])
}
}
// 点击查询,通过公司名获取公司信息
const getBasicInfo = (key) => {}
return (
<Form form={form} name="normal_login">
<Button loading={loadingCompay} type="primary" onClick={() => { getBasicInfo('enterCompanyName')}}>查询</Button>
<Form.Item name="enterCompanyName" label="公司姓名:">
<Select placeholder="请选择" showSearch value={keyword} className="enterCompanyName"
onSearch={debounce(function (value) {
// 模糊搜索获取公司名
getCompany(value)
}, 700)}
onChange={(val: any) => {
// 选中下拉时,也将下拉值作为输入框的值
setKeyword(val)
// 绑定值到表单上
form.setFieldsValue({ enterCompanyName: val })
}}
filterOption={false} //必须加这个,否则会对返回值进行筛选
onBlur={(e: any) => {
// 当是选中值的时候,就没有e.target.value,所以需要通过原生获取节点的值
let value = e.target.value ||
document.getElementsByClassName('enterCompanyName')[0]
?.querySelector('.ant-select-selection-item')?.innerText
// 再次设置关键词
setKeyword(value)
// 绑定值到表单上
form.setFieldsValue({ enterCompanyName: value })
}}
>{companyList.map((item: any, index) => (
<Select.Option key={index} value={item.name}>
{item.name}
</Select.Option>
))}
</Select>
</Form.Item>
</Form>
)
}