记录--按钮防连点终极解决方案

这篇具有很好参考价值的文章主要介绍了记录--按钮防连点终极解决方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--按钮防连点终极解决方案

引言

在日常前端开发中,我们经常会面对一个让人头疼的问题:按钮被用户点击了两次以上,导致出现重复提交表单或者发送重复的请求。这个问题常见而且恼人。为了解决这个问题,我们需要一个又简单又实用的方法,可以在不搞乱原有代码的情况下,有效地防止按钮被连续点击。

背景

随着网页应用变得越来越复杂,用户在页面上的交互也变得越来越频繁。这就使得按钮被不小心点击多次的情况变得非常普遍。一般的解决方法存在一些问题,比如改动原有代码太多,不够灵活等。因此,我们需要一种更好的、通用的按钮防连点方法。

挑战

在解决按钮被连点的问题时,我们要面临一些挑战。首先,解决方法得适应各种情况,比如表单提交、异步请求等。其次,我们需要确保解决方法不会让我们的原有代码变得混乱,同时还要具备足够的灵活性。最后,我们希望不修改原有代码的情况下提供按钮防连点。

目标

本文的目标是为大家提供一个简单易用的按钮防连点解决方案。我们会深入讲解方案的设计原理和实现细节,并且会附上完整的源码解析。通过学习本文,你将能够理解这个解决方案的原理,同时学会如何在实际项目中应用这个方法。希望通过这篇文章,按钮防连点问题不再让你感到头疼,反而变得得心应手。

防连点原理概述

在开始实现我们的按钮防连点终极解决方案之前,让我们首先理解一下连点问题的本质以及为什么传统的解决方案可能存在一些问题。

连点问题的本质

按钮连点问题的核心在于,用户在短时间内多次点击按钮,导致触发相同的操作。这可能引发一系列不良后果,比如重复提交表单、重复发送请求等。为了解决这个问题,我们需要一种机制来在用户点击按钮后一段时间内禁用按钮,防止其再次触发相同的操作。

常规解决方案的局限性

传统的解决方案往往通过在点击按钮后添加禁用状态,然后在一段时间后再启用按钮,来防止连点问题。然而,这种方法存在一些局限性。首先,它可能需要修改原有的按钮组件,使得在多个地方应用时不够灵活。其次,由于采用了定时器等机制,可能导致在某些情况下并不准确,或者在异步操作中存在问题。

给按钮加指令

创建一个可复用的Vue自定义指令,该指令能够动态地管理按钮的状态,以防止用户在短时间内多次点击按钮。关键之处在于,我们还将支持外部传递参数,以自定义按钮的禁用时间。

创建可复用的防连点按钮组件

首先,我们需要创建一个按钮组件,该组件可以接受我们的自定义指令。这样,我们就可以在需要的按钮上应用这个指令。

<template>
  <button v-prevent-duplicate-clicks="2000" @click="handleClick">防连点按钮</button>
</template>

<script>
import preventDuplicateClicks from '@/path-to-your-file/preventDuplicateClicks';

export default {
  directives: {
    preventDuplicateClicks,
  },
  methods: {
    handleClick() {
      // 处理按钮点击事件的业务逻辑
    },
  },
};
</script>

在上述代码中,我们创建了一个按钮组件,通过 v-prevent-duplicate-clicks 指令来防止按钮的连点行为。并且,我们通过传递参数 "2000" 指定了按钮禁用的时间为2秒。

指令文件

现在,创建一个名为 preventDuplicateClicks.js 的文件,该文件包含我们的自定义指令。

// preventDuplicateClicks.js

const preventDuplicateClicks = {
  mounted(el, binding) {
    const { value } = binding;

    el.addEventListener('click', () => {
      if (!el.disabled) {
        el.disabled = true;
        setTimeout(() => {
          el.disabled = false;
        }, value || 1000); // 默认1秒后恢复按钮点击
      }
    });
  },
};

export default preventDuplicateClicks;

在上述代码中,我们定义了一个名为 preventDuplicateClicks 的自定义指令,它在按钮被点击时阻止多次点击。通过 setTimeout 来实现按钮在一定时间后恢复点击。此外,我们在指令上支持了外部参数的传递,用于自定义按钮的禁用时间。

以为估计是80%的前端的解决方案,我在面试中也问过类似的问题,很多人能给出指令的写法已经很好了。有如下问题:

  • 侵入已有代码:如果是老的项目,都要添加这个功能,要去批量改,很麻烦;
  • 禁用时间错误:我们假设给的参数是2秒,一个接口请求超过2秒, 用户在请求响应之前依然会重复发起请求。如果接口几十毫秒就返回(是异常,让重试),用户也得等2秒;

那么有没有更好的解决方案了,肯定是有的,我们来分析以上两个问题:

  • 侵入代码:我们通过重写已有组件可以做到,假设用的el-button,我们在全局把el-button覆盖成我们自己的即可
  • 禁用时间错误:既然设置是错的,那我们就不设置,按钮肯定都有一个onClick的函数,我们只要在onClick执行之前设置禁用,执行后启用即可。

终极解决方案

有了以上的分析,我们直接贴代码吧,我司用的vue + ant design vue,其他组件库,类似写法吧。

<script>
import { Button as AntButton } from 'ant-design-vue'

export default {
  name: 'AButton',
  props: {
    ...AntButton.props,
    delay: {
      type: Number,
      default: 300
    }
  },
  data() {
    return {
      customLoading: false,
      ownDisabled: false
    }
  },
  computed: {
    allProps() {
      return Object.assign({}, this.$props, {
        loading: this.customLoading || this.loading,
        type: this.$props.type || 'primary'
      })
    }
  },
  methods: {
    async handler (...arg) {
      if (this.ownDisabled) return
      this.customLoading = true
      this.ownDisabled = true
      const { click: preClick } = this.$listeners || {}
      const ret = preClick(...arg)
      try {
        await Promise.resolve(ret)
      } finally {
        this.customLoading = false
        let timer = setTimeout(() => {
          this.ownDisabled = false
          clearTimeout(timer)
          timer = null
        }, this.delay)
      }
    }
  },
  render() {
    return (
      <AntButton props={this.allProps} onClick={this.handler}>
        {this.$slots?.default}
      </AntButton>
    )
  }
}
</script>
需要注意的是,使用的时候 onClick 需要返回promise,这算一个很容易遵守的约定吧。另外加个默认延迟300ms,目的我记得好像是为了避免路由跳转时的问题,大家可以自己调整。

本文转载于:

https://juejin.cn/post/7304946949941608475

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--按钮防连点终极解决方案文章来源地址https://www.toymoban.com/news/detail-776964.html

到了这里,关于记录--按钮防连点终极解决方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • win11 无法登录微软账户 终极解决方案

    背景:win11突然无法登录微软账户,office无法激活,Edge里的微软账户也无法登录,反馈中心也无法打开等,有网络,浏览器可以访问微软并进行登录。 试过网上的网络配置(SSL及TLS协议勾选)、DNS配置、网络重置等各项办法均无法。 通过抓包工具发现登录请求应该是指向h

    2024年02月10日
    浏览(40)
  • # Jenkins:一键部署与备份的终极解决方案

    在持续集成和持续部署(CI/CD)的世界中,Jenkins 作为一个开源自动化服务器,扮演着至关重要的角色。但是,部署和维护 Jenkins 服务往往需要一定的技术知识和时间。这里介绍一个强大的工具—— Awesome-Jenkins ,它旨在简化 Jenkins 的部署和任务备份过程。 github地址:https://

    2024年01月19日
    浏览(39)
  • MacBookPro装了Win10没有声音终极解决方案

            MacBookPro装了Win10系统用起来很好,但是有一点不好的就是外放没声音,其它一切都很正常。主要表现为右下角小喇叭图标不可用,设备管理里面相关设备有感叹号。在百度上,搜集了各种解决方案均无果。最终通过大神的帮助解决,本人亲测有效。 MAC BOOK PRO 13 2012

    2024年02月06日
    浏览(88)
  • Kafka消息阻塞:拯救面试的八大终极解决方案!

    大家好,我是小米,一个对技术充满热情的90后程序员。最近在准备社招面试的过程中,遇到了一个超级有挑战性的问题:“Kafka消息阻塞怎么解决?”今天,我就来和大家一起深入剖析这个问题,分享我在解决过程中的心得和经验。 首先,我们得了解一下Kafka消息阻塞是什么

    2024年01月16日
    浏览(37)
  • Nacos:动态服务发现与配置管理的终极解决方案

    今天我想和大家分享一下Nacos,这是一个由阿里巴巴开源的动态服务发现、配置和服务管理平台。我将详细介绍Nacos的主要特性,并通过实例来演示如何使用它。同时,我还会指出Nacos的优点,希望这篇文章能够帮助大家更好地理解和使用Nacos。 Nacos(Dynamic Naming and Configuratio

    2024年02月06日
    浏览(30)
  • 【终极解决方案】IDEA maven 项目修改代码不生效。

    遇到一个非常奇怪的问题, 修改了一个基于maven搭建的SSM项目,但是运行效果仍然是以前的效果,修改没起作用。 这个问题很 邪乎 !写一篇文章总结一下解决方案。 下面是网上常见的解决方案,看官可以先试一下,如果不行,在接下来试我的方案。 《Idea SpringBoot项目修改后

    2024年02月16日
    浏览(39)
  • 安卓高版本安装系统证书 HTTPS 抓包 - 终极解决方案

    要抓App的包,首先需要App信任抓包软件的证书。 不过从Android 从 7.0 开始,系统不再信任用户 CA 证书,所以你需要把 CA 证书安装到系统 CA 证书目录。 如果你是用Magisk越狱的话,这个工作就比较简单了,只需要安装一个模块 Move Certificates。 不过今天的故事从我刷了一个新ro

    2024年02月01日
    浏览(32)
  • ChatGPT扩展系列之ChatHub解决被OpenAI 封号的终极解决方案

    本节介绍了一个解决ChatGPT在中国大陆无法使用和担心被封号的问题的方法。近期有很多亚洲用户被封号,原因是有人滥用API接口或者批量注册账号,不符合官方规定。对于这个问题,提出了一个解决方法,可以在中国大陆无需翻墙使用ChatGPT,并且不用担心被封号。 最近两天

    2024年02月07日
    浏览(61)
  • 终极方案——解决MacBook/Mac mini连接无线鼠标卡顿、漂移

    找到如图设置,修改网络首选项顺序 1、在系统设置里新建一个管理员用户 2、在访达-前往-电脑-磁盘-找到新建用户的那个文件夹,拖至桌面 新用户点击左上角访达设置,在侧边栏显示出硬盘消息

    2024年02月13日
    浏览(31)
  • Ubuntu20.4 WSL2 无法访问github终极解决方案

    sudo rm /etc/resolv.conf sudo bash -c \\\'echo \\\"nameserver 8.8.8.8\\\" /etc/resolv.conf\\\' sudo bash -c \\\'echo \\\"[network]\\\" /etc/wsl.conf\\\' sudo bash -c \\\'echo \\\"generateResolvConf = false\\\" /etc/wsl.conf\\\'      

    2024年02月07日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包