这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
节流
指触发事件后在规定时间内函数只能执行一次,如果在时间范围内再次触发,则会执行最后一次,稀释事件触发频率。达到前端展示及功能的优化。
在开发过程常见场景
scroll,浏览器播放事件等
看下防抖的实现
import { useEffect, useCallback, useRef } from 'react';
function useThrottle(fn, delay, dep = []) {
const { current } = useRef({ fn, timer: null })
useEffect(function () {
current.fn = fn;
}, [fn]);
return useCallback(function f(...args) {
if (!current.timer) {
current.timer = setTimeout(() => {
delete current.timer
}, delay)
current.fn.call(this, ...args)
}
}, dep)
}
export default useThrottle;
防抖
指触发事件后在规定时间内函数,如果在时间不能被重复触发范围内再次触发,则会重新计算函数执行时间。 如果有人点击电梯按钮,就会多等待5秒,此时如果又有人点击,那么电梯就会再多等待 10 秒。
在开发过程常见场景
window resize,鼠标划入划出、keyup、keydown,搜索及表单提交等
实现的时候需要注意一些小问题
1. 增加取消功能
2. 增加立即执行功能
3. `useCallback` 函数的第二个参数,做依赖更新。
4. `useRef` 永久存贮,借助 `useEffect` 更新永久存贮。
看下防抖的实现
import React, { useState, useCallback, useEffect, useRef } from 'react';
const rhDebu: React.FC<any> = () => {
const [count, setCount] = useState<number>(0);
const handleClick = useCallback(data => { console.log(data, 'data'); }, []);
const func = React.useCallback(() => { setCount(count => count + 1); return 2; }, []);
const handleAddCount = UseDebounce(func, 3000, true, handleClick);
return (
<div>
<button onClick={handleAddCount}>count|{count}</button>
</div>
);
};
export default rhDebu;
function UseDebounce( func: any, wait: number, immediate: boolean, callback?: any, ): any {
let timer = useRef<NodeJS.Timeout | null>();
const fnRef = useRef<any>(func); useEffect(() => { fnRef.current = func; }, [func]);
const timerCancel = function() { if (timer.current) clearTimeout(timer.current); };
function debounced(...args: any[]) {
const runFunction = () => {
return callback
? callback(fnRef.current.apply(fnRef.current, args))
: fnRef.current.apply(fnRef.current, args);
};
timerCancel();
if (immediate) {
let runNow = !timer.current;
timer.current = setTimeout(() => { timer.current = null; }, wait);
if (runNow) {
runFunction();
}
} else {
timer.current = setTimeout(() => { runFunction(); }, wait); }
}
debounced.cancel = function() { timerCancel(); timer.current = null; };
return useCallback(debounced, [wait, immediate, timerCancel, func]);
}