1.什么是防抖?
在前端开发中,我们经常会遇到一些高频触发的事件:
-
用户输入框输入 (
onChange
) -
页面滚动 (
onScroll
) -
窗口大小变化 (
resize
)
这些事件如果每次触发都立即执行回调,会带来性能问题。
防抖(Debounce) 的思想就是: 👉 在一段时间内,多次触发只执行最后一次。
打个比方:
-
你在搜索框里疯狂输入,但只想在用户 停下输入 1 秒 后再真正发起搜索请求。
-
这样就避免了每打一个字都请求一次后端。
2常见问题
如果我们不做防抖,代码可能像这样:
javascript
<input onChange={(e) => fetchData(e.target.value)} />
每输入一个字符,就会触发一次 fetchData
,非常浪费资源。 所以我们需要封装一个防抖逻辑。
3.用 React 自定义 Hook 实现防抖
javascript
import { useRef,useEffect } from "react";
export function useFangdou(fn,delay){
const time = useRef(null)
const callback=(a)=>{
if(time.current) clearTimeout(time.current)
time.current=setTimeout(()=>{
fn(a)
},delay*1000)
}
return callback
}
清除上一个定时器,然后执行我们的希望变成防抖的函数执行。
关键点解释
-
useRef
保存定时器-
React 每次渲染函数都会重新执行,但
useRef
保存的值不会丢失。 -
所以我们可以用它来存储
setTimeout
的返回值。
-
-
清理上一次定时器
-
如果在延迟时间内再次触发,先
clearTimeout
,再开新的setTimeout
。 -
这样只会执行最后一次。
-
-
返回一个函数
- 外部直接拿到
useFangdou
返回的callback
去用即可。
- 外部直接拿到
4.使用实例
javascript
import React, { useEffect, useState, useRef } from "react";
import { useFangdou } from "../../stils/useFangdou";
import "./list.css";
export default function List() {
const go = (e) => {
console.log(e.target.value);
};
const scroll = (e) => {
console.log(" ", e);
};
const fangdou = useFangdou(scroll, 1);
const fangdou2 = useFangdou(go, 2);
return (
<div>
<div
className="box"
onScroll={(e) => {
fangdou(e);
}}
>
<div className="child"></div>
</div>
<input
type="text"
onChange={(e) => {
fangdou2(e);
}}
/>
</div>
);
}
这样逻辑就是:
-
每次
text
变化,先清掉上一次的定时器,再开启一个新的setTimeout
; -
2 秒后才执行
console.log
; -
相当于实现了一个输入框的 防抖 (debounce)。