feat: Architecture initialization

This commit is contained in:
2026-07-14 10:31:17 +08:00
commit 6f37264047
59 changed files with 8752 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
// src/hooks/useDebounce.ts
import { watch, onUnmounted } from 'vue';
import { useState } from './useState';
export interface UseDebounceOptions {
delay?: number;
immediate?: boolean;
maxWait?: number;
}
export function useDebounce<T>(
source: any, // Ref<T>
options: number | UseDebounceOptions = {},
) {
const config = typeof options === 'number' ? { delay: options } : options;
const { delay = 300, immediate = false, maxWait } = config;
const [debouncedValue, setDebouncedValue] = useState<T>(source.value);
const [isPending, setIsPending] = useState(false);
let timer: any = null;
let maxWaitTimer: any = null;
let isFirstCall = true; // 标记是否为首次调用,用于 immediate 模式
// 清理
const clearTimers = () => {
if (timer) {
clearTimeout(timer);
timer = null;
}
if (maxWaitTimer) {
clearTimeout(maxWaitTimer);
maxWaitTimer = null;
}
};
// 更新
const updateValue = () => {
setDebouncedValue(source.value);
setIsPending(false);
clearTimers();
// 安静期结束后重置 isFirstCall,使下次触发能立即执行(immediate 模式)
isFirstCall = true;
};
watch(source, () => {
setIsPending(true);
// 处理 maxWait
if (maxWait && !maxWaitTimer) {
maxWaitTimer = setTimeout(() => {
updateValue();
}, maxWait);
}
// 处理 delay
if (timer) clearTimeout(timer);
if (immediate && isFirstCall) {
isFirstCall = false;
updateValue();
} else {
timer = setTimeout(() => {
updateValue();
}, delay);
}
});
// 卸载
onUnmounted(() => {
clearTimers();
});
return {
debouncedValue,
isPending,
refresh: updateValue,
cancel: clearTimers,
};
}