节流 throttle
- 应用: 滚动/拖拽时减少触发频率
- 相当于技能CD
throttle body: 汽车节气门
封装
function throttle(cb: Function, time = 1000) {
let cd = false;
return function (...args: any[]) {
if (cd) return;
cd = true;
cb.call(this, ...args); // 透传this
setTimeout(() => (cd = false), time);
};
}
使用
btn.addEventListener(
"click",
throttle((e) => console.log(e))
);
防抖(dou) debounce
- 应用: 搜索框
- 延迟执行
- 类似于憋大招前的吟唱. 如果大招cd为0, 那么一直不停按大招键,大招将永远释放不出来
- 如果你的只点了一下鼠标就出现了双击,这个时候就需要调整一下你鼠标的
debounce time
写法一
export const useDebounce = (value: any, delay = 300) => {
const [v, setV] = useState(value);
useEffect(() => {
const timer = setTimeout(() => {
setV(value);
}, delay);
return () => clearTimeout(timer);
}, [value, delay]);
return v;
};
cosnt [value, setV] = useState(1)
cosnt debounceValue = useDebounce(value)
写法二
export const useDebounceFn = (cb: Function, delay = 300) => {
const timer = useRef<any>(null);
return (...args: any) => {
clearTimeout(timer.current);
timer.current = setTimeout(() => {
cb.call(undefined, ...args);
clearTimeout(timer.current);
}, delay);
};
};
const fetchSuggest = useDebounceFn((value: string) => {
...
...
});
function onChange(e) {
const value = e.target.value;
setV(value);
fetchSuggest(value);
}
写法三
function debounce(cb: Function, delay = 1000) {
let timer: any;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
cb.apply(this, args); // 透传this, args
}, delay);
};
}
使用
document.getElementById("btn").addEventListener(
"click",
debounce((e) => console.log(e))
);
注意:
- 写法3在react中使用时记得用useCallback将函数缓存起来, 不然每次render都会把timer清空
- react中推荐使用方法1和2
const fetchSuggest = useCallback(debounceFn((value: string) => {
...
...
}))