防抖,节流是前端业务中经常用到的一种优化手段,能极大的节省内存开销和前后端交互次数
我本人防抖用过几次,节流倒是没接触过,于是特地研究了一下,发现这两者其实大同小异;
防抖就是设定一个延迟,在这个延迟时间内如果多次调用,只执行最后一次调用
节流就是设定一个最大时间,在这个时间内管你调用多少次,也只会调用一次,通俗的讲就是采用固定频率
所以这两个本质上没区别,都是为了在多次快速频繁调用时,只调用一次。
不过一个是取最后一次调用,一个是取第一次调用的结果(反正我个人理解是这样😂)
正常业务中,为了适应快速开发,防抖和节流不用自己写,一般用lodash的 debounce 和 throttle
自己手写的话,可以参考如下代码:
防抖
import React, { useState } from "react";
var init1 = 0;
var timer1 = null; //初始化timer,作为计时清除依据
function App() {
const [view1, setView1] = useState(null);
function handleClick1() {
let res = debounce(
function () {
init1++;
setView1(init1);
},
1000,
false
);
res();
}
return (
<div>
<h2>防抖</h2>
<button id="btn" onClick={handleClick1}>
click
</button>
<div id="display" style={{ height: 100 }}>
{view1}
</div>
</div>
);
}
/**
* 防反跳。fn函数在最后一次调用时刻的delay毫秒之后执行!
* @param fn 执行函数
* @param delay 时间间隔
* @param isImmediate 为true,debounce会在delay时间间隔的开始时立即调用这个函数
* @returns {Function}
*/
function debounce(fn, delay, isImmediate) {
console.log("执行");
return function () {
var context = this; //获取函数所在作用域this
var args = arguments; //取得传入参数
clearTimeout(timer1);
if (isImmediate && timer1 === null) {
//时间间隔外立即执行
fn.apply(context, args);
timer1 = 0;
return;
}
timer1 = setTimeout(function () {
fn.apply(context, args);
timer1 = null;
}, delay);
};
}
export default App;
节流
import React, { useState } from "react";
var init2 = 0;
var timer2 = null;
var timeStamp = new Date();
function App() {
const [view2, setView2] = useState(null);
function handleClick2() {
let res = throttle(function () {
init2++;
setView2(init2);
}, 1000);
res();
}
return (
<div>
<h2>节流</h2>
<button id="btn" onClick={handleClick2}>
click
</button>
<div id="display" style={{ height: 100 }}>
{view2}
</div>
</div>
);
}
function throttle(fn, delay) {
return function () {
var context = this; //获取函数所在作用域this
var args = arguments; //取得传入参数
if (new Date() - timeStamp > delay) {
timeStamp = new Date();
timer2 = setTimeout(function () {
fn.apply(context, args);
}, delay);
}
};
}
export default App;
React 自定义Hooks 写法
import { useState, useEffect } from "react";
function useDebounce(value: any, delay = 300) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
}
export default useDebounce;
效果可查看该视频: