做网站一般要多钱,邢台做移动网站的地方,搜索推广营销,做大型网站需要多少钱一、防抖和节流概述
防抖#xff08;debounce#xff09;和节流#xff08;throttle#xff09;是前端经常用到的工具函数。
在进行窗口的resize、scroll#xff0c;输入框内容校验等操作时#xff0c;如果事件处理函数调用的频率无限制#xff0c;会加重浏览器的负担…一、防抖和节流概述
防抖debounce和节流throttle是前端经常用到的工具函数。
在进行窗口的resize、scroll输入框内容校验等操作时如果事件处理函数调用的频率无限制会加重浏览器的负担导致用户体验非常糟糕。此时我们可以采用debounce防抖和throttle节流的方式来减少调用频率同时又不影响实际效果。
通常情况下我们习惯于使用lodash提供的工具函数那么如何自己封装防抖节流的hooks
首先了解下概念
防抖 维护一个计时器规定在delay时间后触发函数但是在delay时间内再次触发的话就会取消之前的计时器而重新设置。这样一来只有最后一次操作能被触发。节流 维护一个计时器规定在delay时间后触发函数但是在delay时间内再次触发的话会判断是否有延迟调用函数未执行有则返回没有则设定在delay时间后触发函数
1、函数防抖
当持续触发事件时一定时间段内没有再触发事件事件处理函数才会执行一次如果设定的时间到来之前又一次触发了事件就重新开始延时。
function debounce(fn, ms) {let timer;return function(...args) {if (timer) {clearTimeout(timer)}timer setTimeout(() {fn(...args)timer null;}, ms);}
}2、函数节流
当持续触发事件时保证一定时间段内只调用一次事件处理函数。
function throttle(fn, ms) { let timer; return function(...args) { if (timer) return;canRun false;timer setTimeout(() { fn(...args);timer null;}, ms); }
} 二、react当中防抖细节
防抖函数必须在只执行一次的位置调用。在类组件中放在constructor里或者变量函数生成的时候都可以因为类组件只会初始化一次后续组件中绑定的函数永远是不变的因此依据闭包原理保存下来的状态会起作用。
而在函数式组件中每次render时内部函数会重新生成并绑定到组件上去。当组件只有一个state会影响render时我们
狂点按钮只会触发点击事件不会重新渲染当前组件绑定的事件函数没有变化防抖函数是同一个因此防抖起作用
但是当有其他state影响渲染后
狂点按钮触发事件不重新渲染count2发生变化重新渲染handleClick重新生成并绑定到组件原有函数失效防抖失效原有函数延迟一定后执行counter1发生变化
流程的对比就是这样了现在你明白为什么正常的防抖函数不能用在 reack hook 里了么
那么怎么实现react hook防抖呢核心思想就是保证每次渲染时绑定到组件上的函数是同一个防抖函数。
防抖hook
import { useCallback, useEffect, useRef } from react;
export interface UseRefParams {fn: (_args: any) void;timer: ReturnTypetypeof setTimeout | null;
}
// React anti shake function
export const useDebounce (fn: (_args: any) void, delay 2000) {const { current } useRefUseRefParams({ fn, timer: null });useEffect(() {current.fn fn;}, [current, fn]);return useCallback((args: any) {if (current.timer) {clearTimeout(current.timer);}current.timer setTimeout(() {current.fn(args);}, delay);},[current, delay]);
};
三 、节流Hook
在react当中节流注意细节与防抖一样这里不做陈述直接上代码
import { useCallback, useEffect, useRef } from react;
export interface UseRefParams {fn: (_args: any) void;timer: ReturnTypetypeof setTimeout | null;
}// React throttling function
export const useThrottle (fn: (_args: any) void, delay 2000) {const { current } useRefUseRefParams({ fn, timer: null });useEffect(function () {current.fn fn;},[current, fn]);return useCallback(function f(args: any) {if (!current.timer) {current.timer setTimeout(() {current.timer null;}, delay);current.fn(args);}},[current, delay]);
};