【JS进阶】防抖与节流

news2024/9/20 22:42:40

防抖与节流

1.防抖

1.1 为什么要防抖?

在项目中,有的操作是高频触发的,但是其实触发一次就好了,比如我们短时间内多次缩放页面,那么我们不应该每次缩放都去执行操作,应该只做一次就好。再比如说监听输入框的输入,不应该每次都去触发监听,应该是用户完成一段输入后再进行触发。

所以,防抖就是防止抖动,避免事件的重复触发

思路:等待用户高频操作完成后,再完成操作。

1.2 基础防抖如何实现?

在这里插入图片描述

基础设计思路:事件触发后,开启一个定时器,当该定时器到时间时,触发操作;而如果事件在该定时器限定的时间内再次触发,则清除当前定时器,并再次开启一个新的定时器。

代码如下:

// fn --- 要执行的操作,delay --- 延迟时间,在该时间内用户没有再次触发则执行操作
function debounce(fn, delay){
    // timer --- 定时器的名称,用于清除定时器
	let timer = null;
	return function(arguments){
         // 实际进行防抖的部分
         // 如果再次触发,首先清除上一次的定时器
		clearTimeout(timer);
         // 创建一个新定时器并记录名称
		timer = setTimeout(()=> {
             // 用apply方法执行目标函数
			fn.apply(this, arguments);
		}, delay)
	}
}

实际上,可以通过下面这张图来理解基础的防抖:

在这里插入图片描述

2.节流

2.1 为什么要节流?

基础的防抖存在一个问题,事件会一直等到用户完成操作后一段时间在操作,如果一直操作,会一直不触发。比如说是一个按钮,点击就发送请求,如果一直点,那么请求就会一直发布出去。这里正确的思路应该是第一次点击就发送,然后上一个请求回来后,才能再发,即节流。

节流就是减少流量,将频繁触发的事件减少,并每隔一段时间执行。即,控制事件触发的频率

思路:某个操作希望上一次的完成后再进行下一次,或者希望隔一段时间触发一次

2.2 如何实现基础节流?

在这里插入图片描述

基础设计思路:我们可以设计一种类似控制阀门一样定期开放的函数,事件触发时让函数执行一次,然后关闭这个阀门,过了一段时间后再将这个阀门打开,再次触发事件。

代码如下:

// fn --- 要执行的操作,delay --- 延迟时间,在该时间内操作最多只会执行一次
function throttle(fn, delay){
    // 阀门是否开启
	let valid = true;
	return function(arguments){
		if(valid) { 
             //如果阀门已经打开,就继续往下,设定定时器,指明在一定延迟时间后执行一次操作
             // 此时已经确定会执行一次操作,因此关闭阀门
			valid = false;
			setTimeout(()=> {
				fn.apply(this, arguments);//定时器结束后执行
				valid = true;//执行完成后打开阀门
			}, delay)
		}
	}
}

实际上,可以通过下面这张图来理解基础的节流:

在这里插入图片描述

3.防抖节流的应用场景、联系以及区别

防抖

  1. search搜索联想,用户在不断输入值时,用防抖来节约请求资源
  2. window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次

节流

  1. 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  2. 监听滚动事件,比如是否滑到底部自动加载更多

联系与区别

防抖节流的共同点在于:都是为了阻止操作高频触发,从而浪费性能。

两者的不同点在于:

  • 防抖是触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计时。适用于可以多次触发但触发只生效最后一次的场景,可能会出现操作始终不执行的情况。
  • 节流则不同,事件高频触发,无论触发多少次,在一定时间内只会执行一次,即定期执行。相比于防抖,节流的响应更加平滑,不会出现始终不执行操作的情况!

4.防抖与节流的优化

对于上面的基础防抖与节流的方法,主要有两个可以优化的方面:

  1. 复用性优化:对于实际项目中,我们不可能在每次需要进行防抖节流的时候,都重新写一遍代码,因此,我们需要将防抖节流的方法封装为内部API提高复用性!
  2. 功能方面的优化
    1. 防抖:添加立即执行选项解决可能始终不执行的问题;延迟防抖,解决高频设定定时器的问题。
    2. 节流:可能需要点击后立即执行等等。

立即执行

在某些业务场景中,使用防抖节流时,基础的防抖节流可能会导致响应时间变长,这就会影响到用户的使用体验,因此,需要在触发事件的时候,立即执行处理函数,但后续也能起到防抖节流的作用。

立即执行的防抖和节流,其原理是一致的,即:添加一个计数器或立即执行的标识

实现如下:

// 防抖
export const debounce = (fun , wait=1000) => {
  let timeout = null
  let count = 0
  return function(){
    let _this = this
    let arg = arguments
    if(timeout){//如果存在定时器就清空
      clearTimeout(timeout)
    }
    if (!count) {
      // 第一次点击时立即执行
      count++
      fun.apply(_this, arg)
      timeout = setTimeout(() => {
        count = 0
      }, wait)
    } else {
      count++
      timeout = setTimeout(() => {
        fun.apply(_this, arg)
        count = 0
      }, wait)
    }
  }
}

// 节流
export const throttled = (fun, wait=1000, immediate) => {
  let preTime = 0;
  let timerId;
  return function() {
    let _this = this;
    let args = arguments;
    if(immediate) { // immediate 为true 时立即执行
      let nowTime = Date.now();
      if(nowTime - preTime > wait) {
        fun.apply(_this, args);
        preTime = nowTime;
      }
    } else {
      if(!timerId) {
        timerId = setTimeout(function() {
          fun.apply(_this, args);
          timerId = null;
        }, wait);
      }
    }
  }
}

其他优化

在不同的业务场景中,对于防抖节流也有不同的需求,如果单纯地为了每一个场景编写防抖节流函数,是相当费事且麻烦的工作,因此,不如使用别人封装好的库。

参考:http://t.csdn.cn/RVzMK

最终解决方案:

underscore.js 库中的 _.throttle()_.debounce() — 参考https://www.likecs.com/show-307738657.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/987621.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

视频直播点播平台EasyDSS视频云平台播放器码率显示不全的原因及其解决办法

EasyDSS互联网视频云平台可提供一站式的视频转码、点播、直播、推拉流、时移回放等服务,也能支持4K视频的直播、点播等功能。EasyDSS可用于视频点播,并支持OBS、推流相机、EasyRTMP等设备的推流直播,可应用在AR、VR、无人机推流、虚拟直播、教…

Word文档超过了20MB如何缩小?文件压缩这样做

在现代办公中,我们常常会遇到各种大小的Word文档,而当一个文档大小超过20MB时,无论是发送还是接收,都会带来诸多不便。那么,如何将过大的Word文档缩小呢?下面,就给大家分享几个简单且实用的方法…

【面试心得】WebBench 整理

在面试九识的时候,被问到了WebBench的原理,当时没答上来,这里做一个整理 WebBench 源码【带注释】:GitHub - YukunJ/annotated-webbench-1.5: bilingually annotated Webbench-1.5 webbench是一个轻量的压测工具,可以…

ipad触控笔是哪几款?开学季性价比电容笔推荐

随着新学期的临近,很多同学都在询问,步入新学期的时候,应该买什么类型的电容笔?苹果的电容笔价格不菲,有必要去选购吗?因为苹果笔拥有着一种特殊的重力压感,所以其的价格很贵,但是其…

Vue中使用qrcode实现渲染生成二维码中间添加自定义logo-demo

效果 安装 npm i qrcode 使用 import QRCode from qrcode; 具体生成过程 <template><div class"banner-login"><img :src"qrDataUrl" /></div> </template><script setup> import { ref, reactive } from vue; …

怎么压缩视频?最新压缩技巧大分享

在日常生活中&#xff0c;我们常常需要处理各种各样的视频文件&#xff0c;有时候&#xff0c;视频文件的大小会成为我们传输和存储的难题。那么&#xff0c;如何有效地压缩视频文件呢&#xff1f;下面就为大家介绍三个实用的方法&#xff0c;让你轻松解决视频大小的问题。 方法…

JS中Promise对象及其使用方式

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是 Promise 对象⭐ 如何使用 Promise⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对We…

第14章 内核空间与用户空间数据交互实验(iTOP-RK3568开发板驱动开发指南 )

在“第12章 字符设备驱动框架实验”中&#xff0c;已经对file_operations结构体的进行了填充&#xff0c;该结构体的每一个成员都对应着一个系统调用&#xff0c;例如read、write等&#xff0c;在对应的实验中&#xff0c;只是对调用函数进行了标志打印&#xff0c;并没有真正实…

Gradle下载库速度过慢解决办法

最近搞了个Gradle的项目&#xff0c;项目下载依赖库太慢了&#xff0c;于是… Gradle下载库速度过慢的问题可能由多种原因导致&#xff0c;以下是一些可能的解决方案&#xff1a; 1、使用国内镜像站点&#xff1a; 你可以改变Gradle的配置&#xff0c;使用国内的镜像站点来下…

如何在本地使用Docker搭建和运行Kubernetes集群

文章目录 1. 准备环境2. 安装Minikube3. 启动Minikube集群4. 验证集群5. 部署一个示例应用创建一个Deployment部署应用检查部署 6. 访问应用创建一个Service部署Service获取Service的访问地址 7. 清理资源结论 &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN…

腾讯云PK阿里云2核2G云服务器租用价格表

2核2G云服务器可以选择阿里云服务器或腾讯云服务器&#xff0c;腾讯云轻量2核2G3M带宽服务器95元一年&#xff0c;阿里云轻量2核2G3M带宽优惠价108元一年&#xff0c;不只是轻量应用服务器&#xff0c;阿里云还可以选择ECS云服务器u1&#xff0c;腾讯云也可以选择CVM标准型S5云…

算法刷题记录-双指针/滑动窗口(LeetCode)

809. Expressive Words 思路 根据题目描述&#xff0c;我们可以知道&#xff0c;如果要将某个单词定义为可扩张&#xff08;stretchy&#xff09;&#xff0c;需要满足如下两个条件&#xff1a; 所以&#xff0c;我们在实现的时候&#xff0c;可以通过两个指针p1和p2&#x…

Reactor模型深度解析

文章目录 Reactor模型深度解析什么是Reactor模型Reactor模型的优势Reactor模型的实现方式同步IO异步IOselectpollepoll Reactor模型的应用场景总结 Reactor模型深度解析 什么是Reactor模型 Reactor模型是一种高并发IO编程模型&#xff0c;它的主要目的是简化IO编程的复杂性&a…

安装Python虚拟环境

环境 python3.10 Ubuntu22.04 首先设置默认python #查看python3 的安装位置 which python3 #设置默认python为 python3 sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 1 #查看是否成功 python --version创建虚拟环境 #安装venv sudo apt i…

【韩顺平】Linux基础

1.网络连接三种方式 1.1 桥接模式&#xff1a;虚拟系统可以和外部系统通讯&#xff0c;但是容易造成IP冲突【1-225】 1.2 NAT模式&#xff1a;网络地址转换模式。虚拟系统可以和外部系统通讯&#xff0c;不造成IP冲突。 1.3 主机模式&#xff1a;独立的系统。 2.虚拟机克隆 3…

Outlook无需API开发连接钉钉群机器人,实现新增会议日程自动发送群消息通知

Outlook用户使用场景&#xff1a; 在企业中&#xff0c;会议和活动的顺利举行对于业务运转和团队协作至关重要。然而&#xff0c;计划的变动总是无法避免&#xff0c;这可能会导致其他人的计划受到影响&#xff0c;打乱原有的安排。为了解决这个问题&#xff0c;许多企业开始使…

Leetcode131. 分割回文串

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 题解&#xff1a;力扣&#xff08…

xargs如何保留文本中的引号

如果文本中有引号&#xff0c;直接用xargs管道操作的话&#xff0c;引号会丢失&#xff0c;如下 该如何保留每一行文本中的引号呢&#xff0c;需要用到xargs的-d选项&#xff0c;设置一个分隔符&#xff0c;这里可以选用换行符来分割 顺便多来一条&#xff0c;直接将文本参数作…

亚马逊秋季促销指南——如何更好的利用促销?

最新消息&#xff0c;亚马逊官方宣布将会在10月份举行Prime会员大促&#xff0c;覆盖多个站点&#xff0c;亚马逊卖家们一定要抓住这波促销机会&#xff0c;在这个秋季再冲一把&#xff01;但是还有一些小白玩家可能对于亚马逊促销了解不够&#xff0c;那么接下来我要讲的这些准…

无涯教程-JavaScript - HEX2OCT函数

描述 HEX2OCT函数将十六进制数转换为八进制数。 语法 HEX2OCT (number, [places])争论 Argument描述Required/Optionalnumber 您要转换的十六进制数。 数字不能超过10个字符(40位)。数字的最高有效位是符号位。其余的39位是幅度位。 负数使用二进制补码表示。 Requiredpla…