本文详解 TypeScript 中防抖(Debounce)与节流(Throttle)函数的实现原理及代码示例。通过具体案例展示如何在输入搜索、窗口调整、滚动监听等场景中应用这两种技术,以优化前端性能并减少不必要的服务器请求。
防抖(Debounce):
防抖机制旨在确保目标函数在设定的时间间隔内仅执行一次。当同一事件在短时间内被多次触发时,防抖会取消之前的执行计划,只有当初始触发后的指定时间窗口内没有新的触发事件发生时,函数才会真正执行。
常见的应用场景包括:
- 输入框实时搜索:当用户在输入框中键入内容时,利用防抖技术延迟执行搜索查询,从而减少不必要的网络请求和服务器负载。
- 窗口大小调整:当用户调整浏览器窗口大小时,使用防抖技术避免在调整过程中频繁重新计算布局,提升页面响应效率。
- 表单验证:在用户输入表单数据时,应用防抖技术,在用户停止输入一段时间后再执行验证逻辑,从而降低验证操作的频率。
/**
* @description 防抖函数
* @param {Function} fn
* @param {number} delay
* @param {boolean} immediate
* @returns {Function}
*/
export function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number,
immediate: boolean = false
): T & { cancel(): void } {
let timerId: ReturnType<typeof setTimeout> | null = null; // 存储定时器
// 定义一个cancel办法,用于勾销防抖
const cancel = (): void => {
if (timerId) {
clearTimeout(timerId);
timerId = null;
}
};
const debounced = function (
this: ThisParameterType<T>,
...args: Parameters<T>
): void {
const context = this;
if (timerId) {
cancel();
}
if (immediate) {
// 如果 immediate 为 true 并且没有正在期待执行的定时器,立刻执行指标函数
if (!timerId) {
fn.apply(context, args);
}
// 设置定时器,在延迟时间后将 timeoutId 设为 null
timerId = setTimeout(() => {
timerId = null;
}, delay);
} else {
// 设置定时器,在延迟时间后执行指标函数
timerId = setTimeout(() => {
fn.apply(context, args);
}, delay);
}
};
// 将 cancel 办法附加到 debounced 函数上
(debounced as any).cancel = cancel;
return debounced as T & { cancel(): void };
}节流(Throttle):
节流机制用于确保目标函数在指定时间间隔内最多只执行一次。无论事件触发的频率多高,节流都会以固定的时间间隔执行函数,从而控制执行频率。
常见的应用场景包括:
- 滚动事件监听:例如在监听页面滚动到底部以加载更多数据时,使用节流技术减少检查滚动位置频率,从而提升页面性能。
- 鼠标移动事件:例如实现拖拽功能时,利用节流技术降低处理鼠标移动事件的频率,优化交互体验。
- 动画效果:在实现基于时间的动画效果时,使用节流技术限制动画帧率,从而降低计算开销。
总之,防抖和节流技术均能在不同场景下提升应用性能。防抖适用于多次触发但只需执行一次的情况,而节流适用于限制连续触发事件的执行频率。
/**
* 节流函数
* @param func 要进行节流的指标函数
* @param delay 节流的工夫距离(毫秒)
* @returns 返回一个通过节流解决的函数
*/
export function throttle<T extends (...args: any[]) => any>(
fn: T,
delay: number
): T {
let lastCall: number | null = null; // 上一次调用的工夫戳
return function (
this: ThisParameterType<T>,
...args: Parameters<T>
): ReturnType<T> | void {
const now = Date.now(); //以后工夫戳
// 如果之前没有调用过,或者工夫距离超过了设定的值,执行指标函数
if (!lastCall || now - lastCall >= delay) {
lastCall = now;
return fn.apply(this, args);
}
} as T;
}以上就是 TypeScript 防抖节流实现示例详解的详细内容,更多关于 TypeScript 防抖节流的资料请关注本站其它相关文章!