antd proFromSelect 懒加载+模糊查询
场景
查询用户的时候数量特别大,有10w条数据,不可能直接全部查询用来展示
所以本文章将讲解如何使用懒加载+模糊查询,解决数量过大的问题
后端代码就不用展示了,很简单的分页查询,主要是前端的逻辑
我把返回的json放到最后了,后端就返回这点东西,入参的话就在queryAllUser函数里面,就三个,一个查询的内容,一个页码一个当页数量
不多说直接上代码
1、标签
react
<ProFormSelect
rules={[
{
required: true,
message: `名字为必填项`,
},
]}
placeholder="请选择"
name="id"
label="名字"
width={`md`}
fieldProps={{
// 可搜索
showSearch: true,
// 多选下通过响应式布局让选项自动收缩
maxTagCount: 'responsive',
// 设置 false 时关闭虚拟滚动
virtual: true,
// 下拉列表滚动时的回调
onPopupScroll: e => handleScroll(e),
// 文本框值变化时回调
onSearch: handleSearchChange,
// 这里可加入自定义加载动画
dropdownRender: menu => (
<>
{menu}
{loading && (
<div
style={{
width: '100%',
height: '50px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Spin />
</div>
)}
</>
)
}}
// 数据
options={dataSource}
/>
2、JS
react
/** 加载动画 */
const [loading, setLoading] = useState(false);
/** 数据 */
const [dataSource, setDataSource] = useState<any>([]);
/** 查询改变的值 */
const [searchChangeValue, setSearchChangeValue] = useState<string>('');
/** 页码 */
const [currentPage, setCurrentPage] = useState<number>(1);
// 下一页
const getNextPage = async () => {
// 等于 -1 就是没值了 不需要再加载了
if (currentPage === -1) {
return;
}
try {
// 查询
const { code, msg, data } = await queryAllUser({
name: searchChangeValue,
currentPage,
pageSize: 10,
});
// code 不等于 001 时 为查询失败
if (code !== "001") {
message.error(msg)
return
}
// 开启加载动画
setLoading(true);
const newData: any = data;
// 第一页的时候 不需要之前的数据(原始数据)
if (currentPage === 1) {
setDataSource([...newData])
} else {
// 不是第一页的时候 把查出来的数据放到原始数据(之前的数据)后
setDataSource((prevData: any) => [...prevData, ...newData]);
}
// 页面 +1
setCurrentPage(pre => (pre += 1));
// 不等于 10个 的时候说明查完了
// 就算刚好最后剩 10个 再走一遍逻辑就好了
if (newData.length !== 10) {
// 关闭加载动画、鼠标滚动时不加载
setCurrentPage(-1);
setLoading(false);
}
} catch (error) {
console.log(error);
} finally {
setLoading(false);
}
};
// 监听滚动条
const handleScroll = (event: any) => {
const { scrollTop, offsetHeight, scrollHeight } = event.target;
if (scrollTop + offsetHeight === scrollHeight) {
// 鼠标滚动时不加载
if (currentPage !== -1) {
getNextPage();
}
}
};
// 防抖函数(搜索时使用)
const debounce = (func: { (value: any): void; apply?: any }, delay: number | undefined) => {
let timerId: string | number | NodeJS.Timeout | undefined;
return (...args: any) => {
clearTimeout(timerId);
timerId = setTimeout(() => {
// eslint-disable-next-line prefer-spread
func.apply(null, args);
}, delay);
};
};
// 搜索
const handleSearchChange = debounce((value: any) => {
// 给查询条件赋值
setSearchChangeValue(value)
const fn = async () => {
try {
// 搜索的时候已经查了第一页了 懒加载从第二页开始查
setCurrentPage(2)
const { code, msg, data } = await queryAllUser({
name: value,
currentPage: 1,
pageSize: 10,
});
if (code !== "001") {
message.error(msg)
return
}
const newData = data;
// 由于查询时从第一页开始就不需要原始数据了
setDataSource([...newData]);
} catch (error) {
console.log(error);
}
};
fn();
}, 1000);
// 页面初始化加载
useEffect(() => {
getNextPage();
}, []);
3、json示例
json
{
"msg": "成功",
"data": [
{
"label": "666",
"value": "666"
},
{
"label": "777",
"value": "777"
}
],
"code": "00100000"
}