还在用 JS 做节流吗?CSS 也可以防止按钮重复点击

news2024/11/16 21:59:25

目录

一、CSS 实现思路分析

二、CSS 动画的精准控制

三、CSS 实现的其他思路

四、总结一下


        众所周知,函数节流(throttle)是 JS 中一个非常常见的优化手段,可以有效的避免函数过于频繁的执行。

        举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

btn.addEventListener('click', _.throttle(save, 300))

        其实除了 JS 方式, CSS 也可以非常轻易的实现这样一个功能,无需任何框架库,一起看看吧。

一、CSS 实现思路分析

        CSS 实现和 JS 的思维不同,需要从另一个角度去看待这个问题。

        比如这里的需要对点击事件进行限制,也就是禁用点击事件,想想有什么方式可以禁用事件,没错,就是pointer-events;

        然后是时间的限制,每次点击后需要自动禁用300ms,时间过后重新恢复,那么,有什么特性和时间以及状态恢复有关呢?没错,就是animation;

        除此之外,还需要有触发时机,这里是点击行为,所以必然和伪类 :active 有关联。

        因此,综合分析,实现这样一个功能需要用到pointer-eventsanimation以及 :active ,那么如何将这些思路串联起来呢?

 

思考3秒...

你想到了吗?

        其实这种场景可以理解成是对 CSS 动画的控制,比如有一个动画控制按钮从禁用->可点击的变化,每次点击时让这个动画重新执行一遍,在执行的过程中,一直处于禁用状态,是不是就达到了“节流”的效果了?

接下来看看具体实现

二、CSS 动画的精准控制

假设有一个按钮,绑定了一个点击事件

<button onclick="console.log('保存')">保存</button>

这时的按钮连续点击就会不断地触发,效果如下

 

下面定义一个关于pointer-events的动画,就叫做 throttle 吧

@keyframes throttle {
  from {
    pointer-events: none;
  }
  to {
    pointer-events: all;
  }
}

很简单吧,就是从禁用可点击的变化。

接下来,将这个动画绑定在按钮上,这里为了方便测试,将动画设置成了2s

button{
  animation: throttle 2s step-end forwards;
}

        注意,这里动画的缓动函数设置成了阶梯曲线,step-end,它可以很方便的控制pointer-events的变化时间点。

有兴趣的可以参考这篇文章:CSS3 animation属性中的steps功能符深入介绍 « 张鑫旭-鑫空间-鑫生活 (zhangxinxu.com)[1]

        如下示意,pointer-events在0~2秒内的值都是none,一旦到达2秒,就立刻变成了all,由于是forwards,会一直保持all的状态

 

最后,在点击时重新执行一遍动画,只需要在按下时设置动画为none就行了

这个技巧之前在这篇文章中有更详细的介绍:CSS 实现按钮点击动效的套路

实现如下

button:active{
  animation: none;
}

为了演示方便,我们暂时把颜色变化也加在动画里

@keyframes throttle {
  from {
    color: red;
    pointer-events: none;
  }
  to {
    color: green;
    pointer-events: all;
  }
}

现在如果文字是red,表示是禁用态,只有是green,才表示可以被点击,非常清晰明了,如下

 

下面是最终点击对比效果,很好地限制了点击频率

 

完整代码如下,就这么几行,如果需要改限制时间,直接改动画时间就行了

button{
  animation: throttle 2s step-end forwards;
}
button:active{
  animation: none;
}
@keyframes throttle {
  from {
    pointer-events: none;
  }
  to {
    pointer-events: all;
  }
}

你也可以查看以下任意链接:

  • CSS throttle (codepen.io)[2]

  • CSS throttle - 码上掘金 (juejin.cn)[3]

  • CSS throttle (runjs.work)[4]

三、CSS 实现的其他思路

还记得之前这一篇文章吗?

还在用定时器吗?借助 CSS 来监听事件

        借用这种思路,也可以很轻松的实现节流的效果。而且为了更好的体验,可以用上真正的按钮禁用

btn.disabled = true

        具体思路是这样的,通过:active去触发transition变化,然后通过监听transition回调去动态设置按钮的禁用状态,实现如下

定义一个无关紧要的过渡属性,比如opacity

button{
  opacity: .99;
  transition: opacity 2s;
}
button:not(:disabled):active{
  opacity: 1;
  transition: 0s;
}

然后监听transition的起始回调

// 过渡开始
document.addEventListener('transitionstart', function(ev){
  ev.target.disabled = true
})
// 过渡结束
document.addEventListener('transitionend', function(ev){
  ev.target.disabled = false
})

        这样做的最大好处是,这部分禁用的逻辑是完全和业务逻辑是解耦的,可以在任意时候,任意场合下无缝接入,也不受框架和环境影响,效果如下

 

完整代码也可以查看以下任意链接:

  • CSS throttle disabled (codepen.io)[5]

  • CSS throttle disabled - 码上掘金 (juejin.cn)[6]

  • CSS throttle disabled (runjs.work)[7]

四、总结一下

        以上通过 CSS 的思路实现了类似“节流”的功能,相比 JS 实现而言,实现更精简、使用更简单,没有框架限制,下面一起总结一下实现要点:

  1. ·函数节流是一个非常常见的优化方式,可以有效避免函数过于频繁的执行

  2. ·CSS 的实现思路和 JS 不同,重点在于在于找到和该场景相关联的属性

  3. ·CSS 实现“节流”其实就是控制一个动画的精准控制,假设有一个动画控制按钮从禁用->可点击的变化,每次点击时让这个动画重新执行一遍,在执行的过程中,一直处于禁用状态,这样就达到了“节流”的效果

  4. ·还可以通过 transition 的回调函数动态设置按钮禁用态

  5. ·这种实现的好处在于禁用逻辑和业务逻辑是完全解耦的

        不过,这种实现方式还是比较有局限的,仅限于点击行为,像很多时候,节流可能会用在滚动事件或者键盘事件上,像这些场景就用传统方式实现就行了。

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

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

相关文章

opencv_c++学习(二十)

一、形态学应用案例 开、闭运算、形态学梯度等原理&#xff1a; 相关函数: morphologyEx(InputArray src, OutputArray dst, int op, lnputArray kernel, Point anchor Point(-1,-1), int iterations 1, int borderType BORDER_CONSTANT, const Scalar & border…

Android中静态和动态文字的绘制和测量

Android中静态和动态文字的绘制和测量 Android中自定义视图的时候存在两种情况&#xff0c;静态文字和动态文字。 顾名思义&#xff0c;静态文字就是显示内容是固定的&#xff0c;不会产生变化的文字&#xff0c;而动态文字则是内容会不断产生变化的文字信息。 在说明为什么…

Revit技巧 | Revit中图元不可见怎么办?

在revit中&#xff0c;控制图元课件性的设置有很多种&#xff0c;因此图元不可见&#xff0c;也会有各种各样的原因&#xff0c;这也是经常困扰新手的问题&#xff0c;下面我把这些解决办法做一些归纳总结。 图元如果过远偏离当前视图的中心&#xff0c;将导致视图不可见这时&…

MySQL:数据库的查询与连接

目录 1.复合查询 1.1 多表查询&#xff08;联合查询&#xff09; 1.2 join on (inner join) 1.3 自连接 1.4 子查询 1.5 合并查询 2.内外连接 3.关于高内聚、低耦合 1.复合查询 1.1 多表查询&#xff08;联合查询&#xff09; 什么是多表插叙&#xff1f;实际开发中往…

网络安全管理员证书有什么用?2023证书怎么考?证书报考条件?

网络安全管理员是做什么工作的呢&#xff1f;现如今&#xff0c;网络高速发展&#xff0c;带动了很多行业的兴起&#xff0c;比如说电商行业&#xff0c;今天已经步入到足不出户即可购物的时代了&#xff0c;当然网络也是一把“双刃剑”&#xff0c;带来了好处的同时&#xff0…

Sui Move Object讲解

要了解Sui的独特特性&#xff0c;首先要了解Sui中以对象为中心的数据模型。 Sui的设计初衷是重新定义数字资产所有权的可能性。重新设计的一个基本部分 — — Sui是以对象为中心的数据模型&#xff0c;也是Sui和其他Layer 1区块链之间的一个显著区别。 其他L1如何处理资产所有…

day8 - 使用不同的滤波核进行图像降噪

本期主要介绍用于图像平滑处理的滤波&#xff0c;分别是方框滤波、均值滤波、中值滤波、高斯滤波&#xff0c;比较不同滤波的效果&#xff1b;并了解自定义滤波器进行图像处理。 完成本期内容&#xff0c;你可以&#xff1a; 会使用方框滤波、均值滤波、中值滤波、高斯滤波进行…

实时聊天组合功能,你了解吗?

你有兴趣安装实时聊天组合功能吗&#xff1f;如果您选择了SaleSmartly&#xff08;ss客服&#xff09;&#xff0c;您的实时聊天插件可以不仅仅只是聊天通道&#xff0c;还可以有各种各样的功能&#xff0c;你不需要包含每一个功能&#xff0c;正所谓「宁缺勿滥」&#xff0c;功…

Windows主机中构建适用于K8S Operator开发环境

基于 win 10 打造K8S应用开发环境 一、wsl子系统安装 在cmd命令行终端或powershell中操作 1.1 确认windows操作系统版本 1.2 开启wsl功能 1.3 wsl配置 PS C:\Users\cpf> wsl提示&#xff1a;适用于 Linux 的 Windows 子系统没有已安装的分发版。可以通过访问 Microsoft St…

使用canvas给图片添加水印

上接文章“图片处理” canvas元素其实就是一个画布&#xff0c;我们可以很方便地绘制一些文字、线条、图形等&#xff0c;它也可以将一个img标签里渲染的图片画在画布上。 我们在上传文件到后端的时候&#xff0c;使用input标签读取用户本地文件后得到的其实是一个Blob对象&a…

Redis7实战加面试题-基础篇(Redis持久化,Redis事务,Redis管道,Redis发布订阅)

Redis持久化 RDB (Redis DataBase) RDB&#xff08;Redis 数据库&#xff09;&#xff1a;RDB 持久性以指定的时间间隔执行数据集的时间点快照。实现类似照片记录效果的方式&#xff0c;就是把某一时刻的数据和状态以文件的形式写到磁盘上&#xff0c;也就是快照。这样一来即使…

HCIA-ARP、MAC、交换机工作原理

目录 万能数据转发模型 ARP协议&#xff1a;地址解析协议 以太网帧的交换 IP地址和Mac地址的区别&#xff1a; 以太网交换机介绍&#xff1a; 交换机的工作原理&#xff1a; ​编辑交换机处理数据的三种方式&#xff1a; Mac表和ARP表的区别&#xff1a; 万能数据转发模…

自定义注解和@Target、@Retention注解的使用

说明&#xff1a;注解可以理解为另一种形式的配置&#xff0c;可用于在类上、方法上等&#xff0c;标志是“”&#xff0c;如重写方法上的“Override”就是一种注解。这里我通过一个实例&#xff0c;来介绍自定义注解和java元注解&#xff08;Target、Retention&#xff09;的使…

案例20:Java物流管理系统设计与实现开题报告

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

ChatGPT全球最大开源平替OpenAssistant:基于Pythia和LLaMA微调而来

论文地址&#xff1a;https://drive.google.com/file/d/10iR5hKwFqAKhL3umx8muOWSRm7hs5FqX/view 项目地址&#xff1a;https://github.com/LAION-AI/Open-Assistant 数据集地址&#xff1a;https://huggingface.co/datasets/OpenAssistant/oasst1 体验地址&#xff1a;http…

Hiredis的基本使用

目录 前言 一.hiredis的安装 二.同步API 2.1.连接Redis数据库 2.1.1 无超时时间&#xff0c;阻塞等待连接 2.1.2 设置超时时间&#xff0c;阻塞等待连接。 2.1.3 非阻塞&#xff0c;不管连接与否&#xff0c;立即返回。 2.2.执行命令 2.2.1 返回执行上下文 2.2.2 没有返回执…

伪类元素的用法总结

1:自闭标签不适用伪类元素 自闭合标签 1. 一般标签   由于有开始符号和结束符号&#xff0c;因此可以在内部插入其他标签或文字。 <p>“绿叶&#xff0c;给你初恋般的感觉。”</p> 2. 自闭合标签   由于只有开始符号而没有结束符号&#xff0c;因此不可以在内…

2023-05-24:为什么要使用Redis做缓存?

2023-05-24&#xff1a;为什么要使用Redis做缓存&#xff1f; 答案2023-05-24&#xff1a; 缓存的好处 买啤酒和喝啤酒的例子可以帮助我们理解缓存的好处。 假设你在超市里买了一箱啤酒&#xff0c;如果你需要每次想喝啤酒就去超市购买&#xff0c;无疑会浪费很多时间和精力…

vue+element纯手工完美模拟实现小米有品网站

一、预览 小米有品官网&#xff1a;小米有品 本作品demo预览地址&#xff1a;点击预览 二、效果图对比 1.官方效果截图&#xff1a; 2.作者实现的demo效果图&#xff1a; 首页&#xff1a; 上新精选&#xff1a; 商品详情&#xff1a; 购物车&#xff1a; 登录&#xff1a; …

【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering(分离对比协同过滤)

【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering&#xff08;分离对比协同过滤&#xff09; 文章目录 【论文阅读】23_SIGIR_Disentangled Contrastive Collaborative Filtering&#xff08;分离对比协同过滤&#xff09;1. 来源2. 介绍3. 模型方法3.1…