自定义hooks的时候 命名必须是小驼峰的写法:例如:useData
Hooks 防抖:
export function useFangFn(params, dely = 200) {
const [state, setState] = useState(params)
let timer = useRef(null).current
// 这里的setvalue==用户使用的setvalue()
const setvalue = useRef(args => {
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(() => {
setState(args)
}, dely)
})
// 返回一个参数 再返回一个方法
return [state, setvalue.current]
}
Hooks 节流:
function useThrottle(params, config = { delay: 1000, leading: false, trailing: true }) {
// 这里定义一个更新的setState 用于每次更新页面 并且初始化一个值
const [state, setState] = useState(params)
// 缓存定时器和上一次执行时间
let timer = useRef(null).current
let provious = useRef(0).current
// 封装一个执行函数
const fnApply = (agrs, now = 0) => {
// 改变上次执行的时间
provious = now
// 当你调用了这个执行函数的时候 你要去想 你要干嘛??
// 调用执行函数肯定要返回给用户东西 要返回什么???
// 返回一个x轴和y轴的数值给用户 使用setState设置值并且更新页面返回给用户
setState(agrs)
// 如果我在执行期间有定时器正在执行的话 那么就会产生错误 所以这个时候 需要清空定时器
timer = null
}
// 定义一个清楚定时器的函数
const clearFn = () => {
if (timer) {
clearTimeout(timer)
timer = null
}
}
// 使用ref缓存一个内部的执行函数 到时候只需要把这个执行函数返回给用户即可 用户可以直接调用 传入参数 然后经过一些判断是调用执行函数还是清楚计时器函数
const fnc = useRef(args => {
let now = Date.now()
// 首先我们的需求就是用户首次进入不执行
// 当我们刚进入的时候 这个上一次等待时间肯定为0 所以 如果为0的时候就给他一个等待时间 这样 就标识为这次已经执行过了 然后就会进行下面的操作
if (!provious && !config.leading) {
provious = now
}
// 否则的话 用户设置了第一次执行 或者这不是第一次进入的话 就给他设定一个等待的时间差
let waiting = config.delay - (now - provious)
// 切记每一次都要清空定时器 如果不清空的话 这边定时器还存在呢 下面的函数又执行了定时器 会出错
clearFn()
// 如果很久都没有执行了 那么刚进入就直接执行 然后直接return 就不走下面了
if (waiting <= 0) {
return fnApply(args, now)
}
// 只有当用户连续触发的时候 来判断是否是最后一次触发
if (config.trailing) {
timer = setTimeout(() => {
fnApply(args, now)
}, waiting)
}
})
// useEffect(() => {
// Object.assign(useThrottle, () => {
// if (timer) {
// clearTimeout(timer)
// timer = null
// provious = 0
// }
// })
// }, [])
// 我们要返回的是数据和一个用户能调用的方法
return [state, fnc.current]
}
hooks ref强制更新: