当前位置: 首页 > news >正文

react防抖和节流hooks封装

一、防抖和节流概述

防抖(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时,我们

  1. 狂点按钮,
  2. 只会触发点击事件,不会重新渲染,
  3. 当前组件绑定的事件函数没有变化,防抖函数是同一个,因此防抖起作用

但是当有其他state影响渲染后

  1. 狂点按钮
  2. 触发事件,不重新渲染
  3. count2发生变化,重新渲染
  4. handleClick重新生成并绑定到组件,
  5. 原有函数失效,防抖失效,原有函数延迟一定后执行
  6. counter1发生变化

流程的对比就是这样了,现在你明白为什么正常的防抖函数不能用在 reack hook 里了么?

那么,怎么实现react hook防抖呢?核心思想就是,保证每次渲染时,绑定到组件上的函数是同一个防抖函数。

防抖hook

import { useCallback, useEffect, useRef } from 'react';
export interface UseRefParams {fn: (_args: any) => void;timer: ReturnType<typeof setTimeout> | null;
}
// React anti shake function
export const useDebounce = (fn: (_args: any) => void, delay = 2000) => {const { current } = useRef<UseRefParams>({ 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: ReturnType<typeof setTimeout> | null;
}// React throttling function
export const useThrottle = (fn: (_args: any) => void, delay = 2000) => {const { current } = useRef<UseRefParams>({ 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]);
};

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Hystrix 线程池策略时使用ThreadLocal
  • 【LeetCode】219.存在重复元素II
  • STM32卡死、跑飞如何调试确定问题
  • CMD运行指令
  • 鸿蒙系统开发【ASN.1密文转换】安全
  • 线程池工具类 Executors源代码详解
  • 基于Redis实现全局唯一id
  • 小试牛刀-Telebot区块链游戏机器人(TS升级)
  • 【Python】数据类型之详讲字符串(下)
  • 全球轻型汽车安全气囊面料市场规划预测:未来六年CAGR为4.3%
  • 1. 什么是操作系统
  • 24年税务师考试补报名即将开始啦
  • ComfyUI插件:ComfyUI layer style 节点(三)
  • unity中实现流光效果——世界空间下
  • python学习之旅(基础篇看这篇足够了!!!)
  • 【跃迁之路】【733天】程序员高效学习方法论探索系列(实验阶段490-2019.2.23)...
  • Apache Pulsar 2.1 重磅发布
  • java8 Stream Pipelines 浅析
  • miaov-React 最佳入门
  • MySQL数据库运维之数据恢复
  • PhantomJS 安装
  • python学习笔记 - ThreadLocal
  • React 快速上手 - 07 前端路由 react-router
  • use Google search engine
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 产品三维模型在线预览
  • 读懂package.json -- 依赖管理
  • 多线程 start 和 run 方法到底有什么区别?
  • 关于字符编码你应该知道的事情
  • 经典排序算法及其 Java 实现
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 使用iElevator.js模拟segmentfault的文章标题导航
  • 问题之ssh中Host key verification failed的解决
  • 我的业余项目总结
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #includecmath
  • #stm32驱动外设模块总结w5500模块
  • $refs 、$nextTic、动态组件、name的使用
  • (arch)linux 转换文件编码格式
  • (C语言)共用体union的用法举例
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (三)c52学习之旅-点亮LED灯
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • .java 9 找不到符号_java找不到符号
  • .net core MVC 通过 Filters 过滤器拦截请求及响应内容
  • .net core Redis 使用有序集合实现延迟队列
  • .net 获取某一天 在当月是 第几周 函数
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • .NET命名规范和开发约定
  • .sh 的运行
  • @for /l %i in (1,1,10) do md %i 批处理自动建立目录
  • @property @synthesize @dynamic 及相关属性作用探究
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务