在React hook中使用防抖节流
防抖和节流
先来介绍一下防抖和节流
防抖:事件触发后延迟n秒在执行,如果在这n秒内再次触发则重新计时。即在一段时间内只允许事件执行一次,常用于表单提交,输入框防抖
节流:事件触发后延迟n秒在执行,并且在这n秒内再次触发事件时不允许执行。即减少一段时间内事件触发的频率,常用与监听滚动条滚动,鼠标移动,窗口大小变化
依据上面的定义可以手写一个防抖和节流
防抖函数
import { useRef, useCallback, useEffect } from 'react'
type FnType = (...arg: any[]) => any
interface RefType {
fn: FnType
timer: NodeJS.Timeout | null
}
function useDebounce(fn: FnType, delay: number, dep: any[] = []) {
// 使用 useRef 的目的是:保留上一次的timer,以至于让 if 语句走通,然后清除上一次的 timer
// 否则,没有清除定时器,达不到防抖效果
const { current } = useRef<RefType>({ fn, timer: null })
return useCallback((...args: any) => {
if (current.timer) {
clearTimeout(current.timer)
}
current.timer = setTimeout(() => {
current.fn(...args)
}, delay)
}, dep)
}
export default useDebounce
节流函数
import { useRef, useCallback, useEffect } from 'react'
type FnType = (...arg: any[]) => any
interface RefType {
fn: FnType
timer: NodeJS.Timeout | null
}
/**
* 节流函数
* @param fn
* @param delay
* @param dep
* @returns
*/
function useThrottle(fn: FnType, delay: number, dep: any[] = []) {
// 使用 useRef 的目的是:保留上一次的timer,以至于让 if 语句走通,然后清除上一次的 timer
// 否则,没有清除定时器,达不到防抖效果
const { current } = useRef<RefType>({ fn, timer: null })
return useCallback((...args: any[]) => {
if (!current.timer) {
current.timer = setTimeout(() => {
current.timer = null
}, delay)
current.fn(...args)
}
}, dep)
}
export default useThrottle