useThrottleFn + useDebounceFn
useThrottleFn: 用来处理函数节流的 Hook。
useDebounceFn: 用来处理防抖函数的 Hook。
防抖、节流是前端最基础的一块知识,也是日常开发中经常使用到的
loadsh、 underscore 等工具库更是已经为我们提供了功能更加完善的防抖节流函数
所以无论是 ahooks、react-use 还是 vueuse,它们封装的防抖节流 hooks 都是基于 lodash 提供的
而我们日常开发中最常见的需要防抖节流的场景
- 函数节流/防抖:比如按钮点击操作
- 值节流/防抖:比如输入框里面的值
武功秘籍
引入和类型声明
ts
import throttle from "lodash/throttle";
import { useMemo } from "react";
import useLatest from "../useLatest";
import useUnmount from "../useUnmount";
import { isFunction } from "../utils";
import isDev from "../utils/isDev";
export interface ThrottleOptions {
wait?: number;
leading?: boolean;
trailing?: boolean;
}
type noop = (...args: any[]) => any;
ts
import debounce from "lodash/debounce";
import { useMemo } from "react";
import useLatest from "../useLatest";
import useUnmount from "../useUnmount";
import { isFunction } from "../utils";
import isDev from "../utils/isDev";
export interface DebounceOptions {
wait?: number;
leading?: boolean;
trailing?: boolean;
maxWait?: number;
}
type noop = (...args: any[]) => any;
具体实现
ts
function useThrottleFn<T extends noop>(
fn: T, // 需要节流的函数
options?: ThrottleOptions // 配置项
) {
// 开发环境提示
if (isDev) {
if (!isFunction(fn)) {
console.error(
`useThrottleFn expected parameter
is a function, got ${typeof fn}
`
);
}
}
// 使用 useLatest(useRef) 封装 fn,包装每次调用的函数地址不会发生变化
const fnRef = useLatest(fn);
// 节流默认时间 1s
const wait = options?.wait ?? 1000;
// 使用 useMemo 缓存经过包装的节流函数
const throttled = useMemo(
() =>
// 调用 loadsh 的节流函数
throttle(
(...args: Parameters<T>): ReturnType<T> => {
return fnRef.current(...args);
},
wait,
options
),
[]
);
// 组件卸载
useUnmount(() => {
throttled.cancel();
});
return {
run: throttled, // 节流函数
cancel: throttled.cancel, // 终端节流函数操作
flush: throttled.flush,
};
}
export default useThrottleFn;
ts
function useDebounceFn<T extends noop>(fn: T, options?: DebounceOptions) {
if (isDev) {
if (!isFunction(fn)) {
console.error(`
useDebounceFn expected parameter
is a function, got ${typeof fn}
`);
}
}
const fnRef = useLatest(fn);
const wait = options?.wait ?? 1000;
const debounced = useMemo(
() =>
debounce(
(...args: Parameters<T>): ReturnType<T> => {
return fnRef.current(...args);
},
wait,
options
),
[]
);
useUnmount(() => {
debounced.cancel();
});
return {
run: debounced,
cancel: debounced.cancel,
flush: debounced.flush,
};
}
export default useDebounceFn;
使用
大侠我懒了,你们自己取官网看吧