使用场景
常见的有例如搜索框输入,鼠标事件,窗口resize等极为敏感的事件中需要用到
使用目的
可以等一等再执行,例如在搜索框搜索时,不用每输入一个字符都发起一次请求,而是等一段时间后再带上最后一次的搜索条件去发起请求
实例
// debounce
const debounce = (func, delay) => {
let timeout;
return (...param) => {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function () {
func(...param);
}, delay);
};
};
const log = debounce(() => console.log("call"), 3000);
log(); // #1
log(); // #2
log(); // #3
可以将其copy到浏览器console台查看结果
debounce原理
3次log()几乎是在0.00几秒之内同步完成的,
在0-------1s过程中
log#1先执行,得到一个timeout#1
log#2执行,看到前面已经有timeout,就将第一个timeout#1删了,生成自己的timeout#2并等待
log#3执行,同样看到前面已经有timeout,就将前面的timeout#2删了,生成自己的timeout#3并等待3秒完成
最终3秒之后只执行了log#3
这是一个鸠占鹊巢,从0开始的骚操作
———补充——————————————————————————————————————
最后来个项目中实际用到的例子吧
antd 搜索框做防抖搜索
封装useDebounce钩子
export const useDebounce = <V>(value: V, delay?: number) => {
//对搜索框输入,鼠标点击等事件实现防抖,如果delay时间内该事件仍然被触发,则摧毁之前的,重新等待delay时间
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(() => {
let timeout = setTimeout(() => {
setDebouncedValue(value)
}, delay)
//卸载组件之前销毁定时器
return () => clearTimeout(timeout)
}, [value, delay])
return debouncedValue;
}
封装debouncedSearch.tsx
import { useEffect, useState } from 'react';
export const DebouncedSearch = (props: any) => {
//保证初始化时不执行,只在debouncedSearch改变时执行
const [isInit, setInit] = useState(true);
const [search, setSearch] = useState<string | null | undefined>(null);
const debouncedSearch = useDebounce(search, 500);
const { onSearch } = props;
useEffect(() => {
if (isInit) {
setInit(false)
} else {
onSearch(debouncedSearch);
}
}, [debouncedSearch]);
return (
<Input.Search
{...props}
onChange={async (e) => {
if (e.target.value.trim() === '') {
setSearch(undefined);
} else {
setSearch(e.target.value);
}
}}
/>
);
};
使用debouncedSearch
<DebouncedSearch
placeholder="搜索"
onSearch={e=>{ /*做点你想做的,查询,搜索等*/ }}
/>