js语法---理解防抖原理和实现方法

什么是防抖(节流)

        在实际的网页交互中,如果一个事件高频率的触发,这会占用很多内存资源,但是实际上又并不需要监听触发如此多次这个事件(比如说,在抢有限数量的优惠券时,用户往往会提前在短时间内高频率的点击按钮,但是我只需要接受多次点击中的一次点击,判断有没有抢到即可),这个时候就需要防抖来减少监听的次数,

        防抖就是在多次触发事件时,减少对冗余事件的监听(主要包括,只保留一次监听一定事件内只触发一次监听),

防抖使用场景 :在原有需求能实现的前提下减少多余操作

原理和示例

事件案例

以下是一个点击事件的展示,我们希望判断这个按钮有没有被点击(只要又打印结果即可)

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>防抖</title>
</head>
<body><button id="bt">点击</button><script src="index.js"></script>
</body>
</html>
const bt = document.getElementById('bt');
const click = () => {console.log('点击了按钮');
}bt.addEventListener('click', click);

可以看到短时间内用户可能会多次点击按钮,但是我们只需要一次打印就可以判断出用户是否点击了按钮,所以这里有16次的事件冗余。 

设置防抖

思路:在用户多次点击按钮时,我们选择保留最后一次事件触发,即在点击到事件触发这段时间,如果用户再点击,则将上一次点击的操作取消,而等待执行新点击的操作,以此类推;

const bt = document.getElementById('bt');
let timer;// 声明一个全局的定时器变量
const click = () => {clearTimeout(timer);// 清除之前的定时器timer = setTimeout(() => { // 延时触发操作console.log('点击了按钮');}, 500);
}bt.addEventListener('click', click);

         这里的代码要注意这个定时器变量,它要在click函数体外,因为它要在click触发时保存上一次的定时器,并对其实现清楚,如果出现在click函数体内,则会因为每次都产生新的定时器且无法捕获到上一次的定时器,而导致所有打印延迟生效,没有被清楚

此时在点击按钮时,不会立刻打印结果,而多次点击时,由于旧的定时器不断被清楚,打印操作都不会被触发,直到停下点击之后的0.5s才会出现打印结果

封装一个防抖函数

了解了防抖的基本实现,我们封装一个防抖函数以便于对函数的时间间隔防抖功能实现,

防抖函数,它应该接受两个参数,一个是要执行的函数一个是执行函数的间隔,并且返回一个有防抖效果的函数

/*** @param fun 要执行的操作* @param time 执行的间隔* @return 返回有防抖效果的原操作* */
const FD = (fun, time) => {let timer;// 闭包储存定时器变量return function () {if (!timer) {timer = setInterval(() => {fun();clearInterval(timer);// 清除定时器timer = null;// 重置定时器变量}, time);}}
}

因为要有一个变量来保存定时器的状态,所以这采用闭包的形式保存这个timer,这样每次执行这个FD的返回函数时,timer的值都会保留下来而不是被覆盖,

关于闭包的解释可以参考:js闭包------简单理解闭包含义_js 闭包累加-CSDN博客

使用实例

监听一个页面滚动的事件,打印出滚动的高度,用防抖减少打印的次数

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>防抖</title>
</head>
<body style="height: 200vh;"><button id="bt">点击</button><script src="index.js"></script>
</body>
</html>
window.onscroll = () => {console.log('滚动的距离', window.scrollY);
}

这里即使是滚动一小段距离也会多次触发打印

滚动了300的距离就触发多次打印,

/*** @param fun 要执行的操作* @param time 执行的间隔* @return 返回有防抖效果的原操作* */
const FD = (fun, time) => {let timer;// 闭包储存定时器变量return function () {if (!timer) {timer = setInterval(() => {fun();clearInterval(timer);// 清除定时器timer = null;// 重置定时器变量}, time);}}
}window.onscroll = FD(() => {console.log('滚动的距离', window.scrollY);
},500);

有了防抖之后,0.5秒只触发一次打印,大大减少了事件触发

完整代码展示

index.html:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>防抖</title>
</head>
<body style="height: 200vh;"><button id="bt">点击</button><script src="index.js"></script>
</body>
</html>

index.js: 

// 1.声明一个变量,储存定时器,
// 2.在点击事件中,先清除之前的定时器,再设置新的定时器,
// 3.设置定时器延时操作,相当于等待操作执行结束,才会执行下一次操作(防抖)const bt = document.getElementById('bt');
let timer;// 声明一个全局的定时器变量
const click = () => {clearTimeout(timer);// 清除之前的定时器timer = setTimeout(() => { // 延时触发操作console.log('点击了按钮');}, 500);
}bt.addEventListener('click', click);// 多次点击,只执行最后一次操作(节流)// 节流/*** @param fun 要执行的操作* @param time 执行的间隔* @return 返回有防抖效果的原操作* */
const FD = (fun, time) => {let timer;// 闭包储存定时器变量return function () {if (!timer) {timer = setInterval(() => {fun();clearInterval(timer);// 清除定时器timer = null;// 重置定时器变量}, time);}}
}// window.onscroll = () => {
//   console.log('滚动的距离', window.scrollY);
// }window.onscroll = FD(() => {console.log('滚动的距离', window.scrollY);
},500);// 滚动时,每隔500ms打印一次滚动的距离

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

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

相关文章

Scott Brinker:API对今天的Martech用户来说「非常重要」 ,但它们对即将到来的人工智能代理浪潮至关重要

API在Martech中非常重要 猜一猜空格应该填什么&#xff1a; _______之于AI代理就像数据之于AI模型 正如你可能从我的标题猜到的那样&#xff0c;答案是API。让我们讨论一下为什么…… 数据是人工智能模型的差异化 在过去的一年半里&#xff0c;人工智能疯狂的超级炒作周期…

LVS+Keepalived 群集部署111

引言 Keepalived 是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可以解决静态路由出现的单点故障问题。

LVS集群,(2)DR模式

直连路由&#xff0c;DR模式&#xff0c;采用半开放式的网络结构&#xff0c;与TUN模式的结构类似&#xff0c;但是DR模式中与调度器应在同一个物理网络中&#xff0c;需要在同一个网段内。 直连路由模式也是LVS默认的模式&#xff0c;应用最广泛&#xff0c;由于是在同一个网…

GPT-4V 和 Gemini对比

GPT-4V 和 Gemini 的原理及对比 GPT-4V和Gemini都是当代领先的多模态AI模型&#xff0c;但它们在设计原理、实现方法和应用场景上有一些显著的区别。下面将详细解释这些模型的原理&#xff0c;并比较它们的优缺点。 GPT-4V 的原理 GPT-4V 是 OpenAI 开发的 GPT-4 的多模态版本…

Repetition Improves Language Model Embeddings论文阅读笔记

文章提出了一种提高decoder-only LLM的embedding能力的方法&#xff0c;叫echo embeddingslast-token pooling&#xff08;即直接选最后一个token作为句子的embedding&#xff09;和直接mean pooling都不如文章提出的echo embedding&#xff0c;做法是把句子重复两次&#xff0…

OpenGL Super Bible 7th - Drawing Our First Triangle(绘制第一个三角形)

简介 本文的原版为《OpenGL Super Bible 7th》,是同事给我的,翻译是原文+译文的形势。文章不属于机器直译,原因在于语言不存在一一对应的关系,我将尽可能的按照中国人看起来舒服的方式来翻译这些段子,如果段子让你感到身心愉悦,那还劳烦点个关注,追个更。如果我没有及时…

类和对象知识点

面向对象概念回顾 万物皆对象 用程序来抽象&#xff08;形容&#xff09;对象 用面向对象的思想来编程 什么是类 基本概念 具有相同特征&#xff0c;具有相同行为&#xff0c;一类事物的抽象。 类是对象的模板&#xff0c;可以通过类创建出对象&#xff0c;类的关键词—…

【论文阅读】-- Attribute-Aware RBFs:使用 RT Core 范围查询交互式可视化时间序列颗粒体积

Attribute-Aware RBFs: Interactive Visualization of Time Series Particle Volumes Using RT Core Range Queries 1 引言2 相关工作2.1 粒子体渲染2.2 RT核心方法 3 渲染彩色时间序列粒子体积3.1 场重构3.1.1 密度场 Φ3.1.2 属性字段 θ3.1.3 优化场重建 3.2 树结构构建与调…

算法题day45(补5.31日卡:动态规划05)

一、完全背包理论基础&#xff1a; 完全背包和01背包问题唯一不通过的地方就是&#xff0c;每种物品有无限件。 二、刷题&#xff1a; 1.卡码网 52. 携带研究材料&#xff08;第七期模拟笔试&#xff09; (kamacoder.com)(medium&#xff09; 解决: nv input().strip().sp…

如何在 Windows 中安装 Spire.PDF for Python

Spire.PDF for Python 是一款完全独立的 PDF 开发组件&#xff0c;用于在任何 Python 应用程序中读取、创建、编辑和转换 PDF 文件。本文将介绍如何在 Windows 中安装 Spire.PDF for Python。 最新python安装激活教程在下方&#xff1a; 步骤1 下载最新版的 Python 并将其安装…

【Leetcode】最后一个单词的长度

给你一个字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。 示例 1&#xff1a; 输入&#xff1a;s "Hello World" 输出&#xff1a;5 …

MYSQL数据库安装

一.编译安装MySQL服务 1.安装环境依赖包 2.将安装mysql 所需软件包传到/opt目录下 mysql-boost-5.7.44.tar tar zxvf mysql-boost-5.7.44.tar.gz 3.配置软件模块 cd /opt/mysql-5.7.44/ cmake \ -DCMAKE_INSTALL_PREFIX/usr/local/mysql \ -DMYSQL_UNIX_ADDR/usr/local/mysq…

MyBatis中获取Mysql数据库插入记录的主键值

在MyBatis中&#xff0c;你可以使用多种方式获取插入记录的主键值。以下是常见的几种方法&#xff1a; 1. 使用 useGeneratedKeys 和 keyProperty 这是MyBatis提供的最直接的方法。在你的Mapper XML文件中&#xff0c;使用 useGeneratedKeys 和 keyProperty 来指定MyBatis在插…

编程都用什么电脑:深入解析编程者的电脑选择之道

编程都用什么电脑&#xff1a;深入解析编程者的电脑选择之道 在数字化浪潮席卷全球的今天&#xff0c;编程已成为一项炙手可热的技能。然而&#xff0c;对于初学者和资深开发者来说&#xff0c;选择一台合适的电脑往往是一项令人困惑的挑战。那么&#xff0c;编程究竟都需要什…

硬盘的缓存有什么作用

硬盘的缓存主要作用体现在以下几个方面&#xff1a; 预读取&#xff1a; 当硬盘受到CPU指令控制开始读取数据时&#xff0c;硬盘上的控制芯片会控制磁头把正在读取的簇的下一个或者几个簇中的数据读到缓存中。由于硬盘上数据存储时是比较连续的&#xff0c;所以读取命中率较高…

马尔可夫性质与Q学习在强化学习中的结合

马尔可夫性质是强化学习&#xff08;RL&#xff09;算法的基础&#xff0c;特别是在Q学习中。马尔可夫性质指出&#xff0c;系统的未来状态只依赖于当前状态&#xff0c;而与之前的状态序列无关。这一性质简化了学习最优策略的问题&#xff0c;因为它减少了状态转移的复杂性。 …

ES8新特性:async函数

1、async函数 返回值为promise对象&#xff1b;promise对象的结果由async函数执行的返回值决定。 2、await 表达式 await 必须写在 async 函数里面&#xff1b;await 右侧的表达式一般为promise对象,返回该对象的结果&#xff0c;如果不是promise对象&#xff0c;就直接返回对…

【云手机】数据安全如何保障?

安全办公&#xff0c;信息安全&#xff0c;这是企业使用云手机的初衷和目的&#xff0c;云手机在数据保密&#xff0c;远程办公等功能上有巨大的优势&#xff0c;也为企业提供了支持 首先就是云手机能够实现数据的集中管理和加密存储。所有办公相关的数据都存储在云端的安全服务…

2024加密软件排行榜|最新企业常用加密软件推荐

安秉网盾加密软件&#xff1a; 专注于企业级的透明加密解决方案&#xff0c;确保公司内部文件在公司环境外无法被访问。 审批机制灵活&#xff0c;支持多种审批方式&#xff0c;方便管理。 广泛应用于多个行业&#xff0c;拥有丰富的企业环境适配经验。 适合对内部数据安全有严…

音乐管理系统 SpringBoot + vue

文章目录 1、简要介绍2、数据库设计3、解决的问题1、图片和音频的上传和存储2、分页功能 4、数据返回 也算是进行了半个学期&#xff0c;跟着老师讲的进行 后端使用SpringBoot 前端 vue layui jdk 18 项目地址&#xff1a;gitee 1、简要介绍 只有管理端&#xff0c;但是对用…