前阵子在打游戏,突然想起来前端貌似是有什么防抖、节流,就百度了一下,看了一眼没看懂,过了好久才又想起来,遂照着别人的代码码了一下。
参考:
- 经典防抖:人类高质量JS防抖与节流机制
- hooks防抖:React hooks 怎样做防抖?
因为我用的react hooks写的项目,看完经典防抖直接就去试了一下,发现不行,感觉是因为react hooks的特性引发的问题,又去找了一篇react hooks有关的知乎,二者结合了一下,成功。
核心debounce.js
文件:
import {
useCallback, useEffect, useRef } from "react"
function useDebounce(fn, delay, dep = []) {
// useRef 可以跨周期保存数据,不会因重新渲染而被重置,这样定时器就有效了
// 只有单击和连击的最后一次会生效
const {
current } = useRef({
fn, time: null, firsttime: true })
useEffect(function () {
current.fn = fn
}, [fn])
return useCallback(function f(...args) {
current.firsttime = !current.time
if (current.firsttime) {
// 依然没搞清楚为什么call 这里不call也能成功
// current.fn.call(this, ...args)
current.fn(...args)
}
if (current.time) {
clearTimeout(current.time)
}
current.time = setTimeout(() => {
current.time = null
if (!current.firsttime) {
// current.fn.call(this, ...args)
current.fn(...args)
}
}, delay)
}, dep)
}
export default useDebounce
应用:
import {
login } from '../../service/services'
import Debounce from '../../utils/debounce.js'
function Login () {
// success
// 注意 这里Debounce必须处于顶层,也就是直接赋值给dologin常量,否则会违反react hooks 的规则 爆红
const dologin = Debounce(() => {
login(state).then(res => {
if (res) {
if (res.status === 200) {
console.log('登陆成功!')
} else {
message.error(`${
resp.msg}`)
}
}
})
}, 1000)
return (
<>
<Button
onClick={
() => {
dologin()
}}
}}
>
登录
</Button>
</>
)
}
export default Login
为了方便阅读,我将不相关的其他代码都删掉了。