返回首页
浅谈防二次点击方法
发表时间:2022-04-20 阅读:1713
新零售系统
Java商城
多用户商城
浅谈防二次点击方法

一、用遮罩层处理

uni.showLoading({ title: '加载中',mask:true });//防止连续二次点击

处理后:用uni.hideLoading()清除遮罩层

 

二、@click.once

但只能点击一次,如果不是点击马上跳转的话,或者有检测条件的话,就不能用该方法

三、用组件

以下以封装一个button为例,详细说明异步处理防二次点击的方法,该组件除了防二次点击外,还包含uni-app原生button组件的功能:

3.1 子组件里的HTML:

<template>

    <button

        :size="size"

        :type="type"

        :plain="plain"

        :disabled="disabledData"

        :loading="loadingData"

        :form-type="formType"

        :open-type="openType"

        :hover-class="hoverClass"

        :hover-start-time="hoverStartTime"

        :hover-stay-time="hoverStayTime"

        

        :class="className"

        :style="optionstyle"

        @click="clickButton"

    >

        <text>{{text}}</text>

    </button>

</template>

 

3.2 子组件里的JS:

<script>

export default {

       props: {

            className: String ,//类名

            

            options: Object, //设置按钮的文字颜色、背景颜色、文字大小、弧度

            /*  例如:

                :options="{cl:'#666',bc:'#fff',fs:'28',lh:'2.2',bd:'var(--mainColor)',br:'10',pl:'10',pr:'10'}",

                cl:文字颜色(默认值#333333),

                bc:背景颜色(默认值#ffffff),

                fs:文字大小(单位rpx,默认值28),

                lh:X倍行距,例如lh:'2.2'就是2.2倍行距(默认值normal),可以传px,如:lh:'44px',lh:'44rpx'

                bd:border线颜色,例如:bd:'var(--mainColor)'(border颜色为主题色),当不传bd值时,默认值border=0。当传bd值时,border默认是1px,

                bdSet:自定义border线(当有bdSet值时,bd值会失效),例如:bdSet:2px solid var(--mainColor)

                br:弧度(默认值0),

                pl:padding-left,默认值0,单位:rpx

                pr:padding-right,默认值0,单位:rpx

            */

            

            text:{//按钮里的文字,必传

                type: String,

                default: ''

            },

            time:{//防二次点击的默认时间,默认单位是毫秒。

                type: Number,

                default: ''

            },

            clickBtn:Function,//接收外面的方法,因为存在异步的要求,所以不用this.$emit('clickBtn')来传递值

            

            

            size: {//按钮的大小:default:默认大小; mini:小尺寸

             type: String,

             default: 'default'

            },

            type: {//按钮的样式类型:default:白色; warn:红色; primary:微信小程序为绿色,App、H5、百度小程序、支付宝小程序为蓝色,头条小程序为红色,QQ小程序为浅蓝色

             type: String,

             default: 'default'

            },

            plain: {//按钮是否镂空,背景色透明。

             type: Boolean,

             default: false

            },

            disabled: {//是否禁用

             type: Boolean,

             default: false

            },

            loading: {//名称前是否带 loading 图标

             type: Boolean,

             default: false

            },

            formType: {//用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件

             type: String,

             default: ''

            },

            openType: {//开放能力。contact:打开客服会话,share:触发用户转发,getUserInfo:获取用户信息(手机号、头像、昵称等),getPhoneNumber:获取用户手机号,launchApp:打开APP,openSetting:打开授权设置页

             type: String,

             default: ''

            },

            hoverClass: {//指定按钮按下去的样式类。当 hover-class="none" 时,没有点击态效果

             type: String,

             default: 'button-hover'

            },

            hoverStartTime: {//按住后多久出现点击态,单位毫秒

             type: Number,

             default: 20

            },

            hoverStayTime: {//手指松开后点击态保留时间,单位毫秒

             type: Number,

             default: 70

            },

        },

 

data() {

return {

                allowClick:true,//记录是否允许点击按钮(防二次点击用)

                disabledData:this.disabled,//点击后,异步请求完后,才允许点击

                loadingData:this.loading,//

            };

},

 

computed: {

            // 由于:style只能绑定一个值(用官方写法,只有最后一个值会生效),所以要将所有值集中处理

optionstyle() {

                let optionsArr = []

                

                // 处理按钮里的文字颜色

                let color1 = ''

                if (this.options&&this.options.cl) {

                    color1 = `color:${this.options.cl}`

                    optionsArr.push(color1)

                }else{

                    color1 = "color:#333333"

                    optionsArr.push(color1)

                }

                

                // 处理按钮背景颜色

                if(!this.plain){//如果没有设置透明,才显示背景

                    let backgroundColor1 = ''

                    if (this.options&&this.options.bc) {

                        backgroundColor1 = `background-color:${this.options.bc}`

                        optionsArr.push(backgroundColor1)

                    }else{

                        backgroundColor1 = "background-color:#ffffff"

                        optionsArr.push(backgroundColor1)

                    }

                    

                }

                

                // 处理按钮文字大小

                let fontSize1 = ''

                if (this.options&&this.options.fs) {

                    fontSize1 = `font-size:${this.options.fs}rpx`

                    optionsArr.push(fontSize1)

                }else{

                    fontSize1 = "font-size:28rpx"

                    optionsArr.push(fontSize1)

                }

                

                // 处理行距

                let lineHeight1 = ''

                if (this.options&&this.options.lh) {

                    lineHeight1 = `line-height:${this.options.lh}`

                    optionsArr.push(lineHeight1)

                }else{

                    lineHeight1 = "line-height:normal"

                    optionsArr.push(lineHeight1)

                }

                

                // 处理border线

                let border1 = ''

                if(this.options&&this.options.bdSet){

                    border1 = `border:${this.options.bdSet}`

                    optionsArr.push(border1)

                }else if (this.options&&this.options.bd) {

                    border1 = `border:1px solid ${this.options.bd}`

                    optionsArr.push(border1)

                }else{

                    border1 = "border:0"

                    optionsArr.push(border1)

                }

                

                // 处理border线弧度

                let borderRadius1 = ''

                if (this.options&&this.options.br) {

                    if (this.options.br.indexOf("%")>-1) {

                        borderRadius1 = `border-radius:${this.options.br}`

                    }else{

                        borderRadius1 = `border-radius:${this.options.br}rpx`

                    }

                    optionsArr.push(borderRadius1)

                }else{

                    borderRadius1 = "border-radius:0"

                    optionsArr.push(borderRadius1)

                }

                

                // 处理padding-left

                let paddingLeft = ''

                if (this.options&&this.options.pl) {

                    paddingLeft = `padding-left:${this.options.pl}rpx`

                    optionsArr.push(paddingLeft)

                }else{

                    paddingLeft = "padding-left:0"

                    optionsArr.push(paddingLeft)

                }

                

                // 处理padding-left

                let paddingRight = ''

                if (this.options&&this.options.pr) {

                    paddingRight = `padding-right:${this.options.pr}rpx`

                    optionsArr.push(paddingRight)

                }else{

                    paddingRight = "padding-right:0"

                    optionsArr.push(paddingRight)

                }

 

                return optionsArr.toString().replace(/,/g, ';')

},

},

 

methods: {

            async clickButton(){

                this.disabledData=true

                this.loadingData = true

                if(this.time){

                    await this.clickBtn()

                    setTimeout(()=>{

                        this.disabledData=false

                        this.loadingData = false

                    },this.time)

                }

                if(!this.time){

                    await this.clickBtn()

                    this.disabledData=false

                    this.loadingData = false

                }

            },

        }

};

</script>

 

<style lang="stylus" scoped>

    // 备注:rpx传值的话要写在HTML内联里,不然会出现先换算,再拿值,就会rpx值永远也不会根据屏幕大小来换算

    // button{

        // &[loading]:before {width: 25px;height: 25px;};

    // }

</style>

 

3.3 父组件里引用:

    一、有定时器的,如:

        HTML里:

        底部透明的“搜索”按钮,定时器::time="1000"异步方法完成后再等1秒才能点击按钮,loading时间为:1秒+异步方法的运行时间

         <ls-button class="w-auto flex-center" :text="'搜索'" :plain="true"  :clickBtn="searchSeller" :time="1000" :options="{cl:'#ffffff',lh:'44px',pr:'10'}"/>

        

        JS里(注意:要用Promise异步处理,来防止重复点击问题--就算是设置了time,也要用Promise异步处理):

        searchSeller(){

            return new Promise((resolve, reject) => {

                appShopList.loadListByPage( this,this.params, {complete(){resolve(true)}} )

            })

         },

 

    二、没有定时器的,如:

        HTML里:

        显示灰色字、白色背景、28rpx字体、2.2倍行距、绿色边框、10rpx圆角 的“搜索”按钮

        <ls-button :className="'w-100'" :text="'搜索'" :clickBtn="searchSeller" :options={cl:'#666',bc:'#fff',fs:'28',lh:'2.2',bd:'var(--mainColor)',br:'10'}/>

 

四、用指令

快速点击按钮会重复多次调用接口,防止出现这样的情况

 

全局定义,方便调用

新建plugins.js

export default {

  install (Vue) {

    // 防重复点击(指令实现)

    Vue.directive('preventReClick', {

      inserted (el, binding) {

        el.addEventListener('click', () => {

          if (!el.disabled) {

            el.disabled = true

            setTimeout(() => {

              el.disabled = false

            }, binding.value || 3000)

          }

        })

      }

    })

  }

}

 

main.js引用

import preventReClick from '@/utils/plugins.js';Vue.use(preventReClick);

 

按钮调用直接加v-preventReClick

<el-button type="prismary" style="width:100%;" @click="handleSubmit" v-preventReClick></el-button>


文章来源:广州朗尊软件科技有限公司
【朗尊软件】是中国领先的专业电商平台提供商,秉承着“专业塑造传奇,用心成就电商”的理念, 专注于为用户提供一体化的电商解决方案及服务,搭建垂直行业垂直电商一站式营销管理工具。目前拥有自主研发的电子商务平台产品:SAAS云平台、微商城小程序、云商城、云小店、代理商平台、B2B2C商城、B2B大宗交易平台、跨境电商服务、大数据平台搭建、微服务架构等产品、各种定制商城及解决方案。
网站声明:以上内容为朗尊软件官方网站的原创文章,如需转载,请注明出处,谢谢合作!
上一篇: 朗尊电商平台端和商家端开发规范流程
下一篇: 浅谈Flex 布局
相关文章
电子商务系统数据安全的重要性 - 朗尊软件,企业级电商平台提供商
b2b2c商城系统有哪些开发方式?
自建商城系统的优点 - 朗尊软件,企业级电商平台提供商
开源商城系统介绍企业写开源多用户商城 - 朗尊软件,企业级电商平台提供商
供应链金融浅析 - 朗尊软件,企业级电商平台提供商
电商头条新闻
1
工业行业 | 工业产品B2B跨境电商解决方案
2
私域电商如何赶上智能热潮?
3
三一全球购 | B2B2C电商平台+员工福利平台的定制解决方案
4
跨境电商 | B2B2C跨境电商系统解决方案
5
社群团购系统——社区流量与社交电商融合
热门标签
小羊直播
供应链
电商系统
Java商城
电商平台
B2B商城
跨境电商
商城平台
新零售系统
云商城系统
B2B2C商城系统
多用户商城
微服务商城
供应链商城
商城系统
电商直播系统
私域电商
大宗交易平台
数字化转型
直播供应链
全渠道零售
O2O商城系统
java开源商城
SAAS云平台
B2C商城系统
SaaS系统
生鲜电商
用户标签
APP
S2B
MRO平台
微信小程序商城
移动商城
社区电商
营销活动
新零售电商
分销系统
门店管理
分销体系
社交电商
直播电商
数字化
客服系统
社群电商
引爆流量
供应链金融
员工福利平台
工会福利商城
企业智慧采购平台
机械设备
抖音电商
数智化
数字化
区块链
S2B2C
B2B2B
订单融资
数字中台
VUE
用户标签
仓单融资
大数据
应收账款
集采代采
医药电商
推荐阅读
公告:【微信小程序备案】9月1日起,微信小程序需完成备案才可上架!
工业行业 | 工业产品B2B跨境电商解决方案
私域电商如何赶上智能热潮?
三一全球购 | B2B2C电商平台+员工福利平台的定制解决方案
跨境电商 | B2B2C跨境电商系统解决方案