1. 代码封装
import React, { useState } from 'react';
import { Spin } from 'antd';
import './index.scss';
// 自定义Hook useLoadings
export const useLoadings = () => {
// 存储loading的状态,key是loading的唯一标识,value是loading的显示状态
const [loadings, setLoadings] = useState<Record<string, boolean>>({});
const [keyMap, setKeyMap] = useState({});
/**
* @description 随机生成key
* @param length
* @returns { str }
*/
function generateRandomString(length: any) {
const len: number = typeof length === 'number' && length > 0 ? length : 10;
const characters: string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()';
let result: string = '';
const charactersLength:number = characters.length;
for (let i = 0; i < len; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
// 添加loading
const addLoading = (tip: any): string => {
let key:string;
do {
key = generateRandomString(10);
} while (loadings[key]); // 当 loadings[key] 存在时继续循环
setKeyMap((pervKeyMap) => ({
...pervKeyMap,
[key]: tip
}))
setLoadings((prevLoadings) => ({
...prevLoadings,
[key]: true,
}));
return key;
};
// 移除指定的loading
const closeLoading = (key: string) => {
setKeyMap((pervKeyMap) => ({
...pervKeyMap,
[key]: ''
}));
setLoadings((prevLoadings) => ({
...prevLoadings,
[key]: false,
}));
};
// 移除所有loading
const clearAllLoadings = () => {
setLoadings({});
setKeyMap({});
};
// 渲染所有loading
const LoadingIndicators = () => (
<>
{
Object.keys(loadings).map((key) => (
<Spin
key={key}
className='loading-ref'
fullscreen
spinning={loadings[key]}
tip={keyMap[key]}
/>
))
}
</>
);
return {
addLoading,
closeLoading,
clearAllLoadings,
LoadingIndicators,
};
};
index.scss优化样式防止抽屉z-index:1000
挡住
.loading-ref{
z-index: 1001;
}
2. 实际使用
import { useLoadings } from './components/Loading';
import { useEffect } from "react";
export function DomC(){
const {
addLoading,
closeLoading,
clearAllLoadings,
LoadingIndicators
} = useLoadings();
const clickNode = () => {
const loading = addLoading('加载中...');
setTimeout(() => {
closeLoading(loading);
}, 2000);
}
useEffect(() => {
//
return () => {
clearAllLoadings();
}
}, []);
return <>
<div onClick={clickNode}>按钮</div>
<LoadingIndicators />
</>
}