107 lines
2.4 KiB
TypeScript
107 lines
2.4 KiB
TypeScript
// src/utils/debounce.ts
|
|
import { ref } from 'vue';
|
|
|
|
/**
|
|
* 通用防抖函数
|
|
* @param func 需要防抖的函数
|
|
* @param delay 延迟时间(毫秒)
|
|
* @param immediate 是否立即执行
|
|
* @returns 防抖后的函数
|
|
*/
|
|
export function debounce(func: Function, wait: number, immediate: boolean = false) {
|
|
let timeout: NodeJS.Timeout | null;
|
|
|
|
return function (this: any, ...args: any[]) {
|
|
const context = this;
|
|
const later = function () {
|
|
timeout = null;
|
|
if (!immediate) func.apply(context, args);
|
|
};
|
|
const callNow = immediate && !timeout;
|
|
if (timeout) clearTimeout(timeout);
|
|
timeout = setTimeout(later, wait);
|
|
if (callNow) func.apply(context, args);
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 防抖状态管理类
|
|
* 用于管理多个防抖状态
|
|
*/
|
|
export class DebounceManager {
|
|
private states: Map<string, boolean> = new Map();
|
|
|
|
/**
|
|
* 设置防抖状态
|
|
* @param key 状态标识
|
|
* @param value 状态值
|
|
* @param duration 状态持续时间(毫秒)
|
|
*/
|
|
setState(key: string, value: boolean, duration?: number): void {
|
|
this.states.set(key, value);
|
|
|
|
if (value && duration) {
|
|
setTimeout(() => {
|
|
this.states.set(key, false);
|
|
}, duration);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 获取防抖状态
|
|
* @param key 状态标识
|
|
* @returns 状态值
|
|
*/
|
|
getState(key: string): boolean {
|
|
return this.states.get(key) || false;
|
|
}
|
|
|
|
/**
|
|
* 重置所有状态
|
|
*/
|
|
reset(): void {
|
|
this.states.clear();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vue组合式API防抖函数
|
|
* @param delay 延迟时间(毫秒)
|
|
* @returns 包含防抖状态和控制函数的对象
|
|
*/
|
|
export function useDebounce(delay: number = 1000) {
|
|
const isProcessing = ref(false);
|
|
|
|
const debounce = <T extends (...args: any[]) => Promise<any>>(
|
|
func: T
|
|
): ((...args: Parameters<T>) => Promise<ReturnType<T> | void>) => {
|
|
return async (...args: Parameters<T>): Promise<ReturnType<T> | void> => {
|
|
// 如果正在处理中,则阻止新的调用
|
|
if (isProcessing.value) {
|
|
return;
|
|
}
|
|
|
|
isProcessing.value = true;
|
|
|
|
try {
|
|
const result = await func(...args);
|
|
return result;
|
|
} finally {
|
|
// 延迟重置状态,防止快速重复点击
|
|
setTimeout(() => {
|
|
isProcessing.value = false;
|
|
}, delay);
|
|
}
|
|
};
|
|
};
|
|
|
|
const reset = () => {
|
|
isProcessing.value = false;
|
|
};
|
|
|
|
return {
|
|
isProcessing,
|
|
debounce,
|
|
reset
|
|
};
|
|
} |