feat: 实现 Socket 触发的智能列表自动刷新功能(带防抖)
核心改动: - 扩展 NotificationContext,添加事件更新回调注册机制 - VirtualizedFourRowGrid 添加 forwardRef 暴露 getScrollPosition 方法 - DynamicNewsCard 实现智能刷新逻辑(根据模式和滚动位置判断是否刷新) - Community 页面注册 Socket 回调自动触发刷新 - 创建 TypeScript 通用防抖工具函数(debounce.ts) - 集成防抖机制(2秒延迟),避免短时间内频繁请求 智能刷新策略: - 纵向模式 + 第1页:自动刷新列表 - 纵向模式 + 其他页:不刷新(避免打断用户) - 平铺模式 + 滚动在顶部:自动刷新列表 - 平铺模式 + 滚动不在顶部:仅显示 Toast 提示 防抖效果: - 短时间内收到多个新事件,只执行最后一次刷新 - 减少服务器压力,提升用户体验 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
90
src/utils/debounce.ts
Normal file
90
src/utils/debounce.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
// src/utils/debounce.ts
|
||||
// 防抖工具函数(TypeScript 版本)
|
||||
|
||||
/**
|
||||
* 防抖函数返回类型
|
||||
* @template T - 原函数类型
|
||||
*/
|
||||
export interface DebouncedFunction<T extends (...args: any[]) => any> {
|
||||
/**
|
||||
* 执行防抖后的函数
|
||||
* @param args - 原函数的参数
|
||||
*/
|
||||
(...args: Parameters<T>): void;
|
||||
|
||||
/**
|
||||
* 取消待执行的函数调用
|
||||
*/
|
||||
cancel: () => void;
|
||||
}
|
||||
|
||||
/**
|
||||
* 防抖函数 - 延迟执行,短时间内多次调用只执行最后一次
|
||||
*
|
||||
* 工作原理:
|
||||
* 1. 调用防抖函数时,清除之前的定时器
|
||||
* 2. 设置新的定时器,延迟 delay 毫秒后执行
|
||||
* 3. 如果在延迟期间再次调用,重复步骤 1-2
|
||||
* 4. 只有最后一次调用会在延迟后实际执行
|
||||
*
|
||||
* 使用场景:
|
||||
* - 搜索框输入:用户停止输入后才发送请求
|
||||
* - 窗口 resize:窗口调整结束后才重新计算布局
|
||||
* - Socket 事件:短时间内收到多个事件,只处理最后一个
|
||||
*
|
||||
* @template T - 函数类型(泛型约束:任意函数)
|
||||
* @param {T} func - 要防抖的函数
|
||||
* @param {number} delay - 延迟时间(毫秒)
|
||||
* @returns {DebouncedFunction<T>} 防抖后的函数(带 cancel 方法)
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 示例 1:无参数函数
|
||||
* const debouncedSave = debounce(() => {
|
||||
* console.log('保存数据');
|
||||
* }, 1000);
|
||||
*
|
||||
* debouncedSave(); // 1秒后执行
|
||||
* debouncedSave(); // 取消上次,重新计时 1 秒
|
||||
* debouncedSave.cancel(); // 取消执行
|
||||
*
|
||||
* // 示例 2:带参数函数
|
||||
* const debouncedSearch = debounce((keyword: string) => {
|
||||
* console.log('搜索:', keyword);
|
||||
* }, 500);
|
||||
*
|
||||
* debouncedSearch('react'); // 500ms 后执行
|
||||
* debouncedSearch('redux'); // 取消上次,重新计时
|
||||
* ```
|
||||
*/
|
||||
export function debounce<T extends (...args: any[]) => any>(
|
||||
func: T,
|
||||
delay: number
|
||||
): DebouncedFunction<T> {
|
||||
// 使用 NodeJS.Timeout 类型(支持浏览器和 Node 环境)
|
||||
let timerId: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
// 防抖函数主体
|
||||
const debouncedFn = (...args: Parameters<T>): void => {
|
||||
// 清除之前的定时器(防抖核心逻辑)
|
||||
if (timerId !== null) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
|
||||
// 设置新的定时器
|
||||
timerId = setTimeout(() => {
|
||||
func(...args);
|
||||
timerId = null; // 执行后重置定时器 ID
|
||||
}, delay);
|
||||
};
|
||||
|
||||
// 添加 cancel 方法(用于组件卸载时清理)
|
||||
debouncedFn.cancel = (): void => {
|
||||
if (timerId !== null) {
|
||||
clearTimeout(timerId);
|
||||
timerId = null;
|
||||
}
|
||||
};
|
||||
|
||||
return debouncedFn;
|
||||
}
|
||||
Reference in New Issue
Block a user