對于防止按鈕重復(fù)點(diǎn)擊的嘗試詳解
導(dǎo)語:隨著接觸的項(xiàng)目增加,很多項(xiàng)目都是遇到同樣的問題,而每次都是使用一貫的手法進(jìn)行處理。有時(shí)候有些方法并不是那么的優(yōu)雅甚至有些冗余,所以自己也想開始嘗試不同的方法去解決同樣的問題。
我經(jīng)常在項(xiàng)目中會(huì)遇到按鈕重復(fù)點(diǎn)擊后引起表單的重復(fù)點(diǎn)擊問題。所以針對這個(gè)問題,自己嘗試了幾種辦法分別去解決。直接上代碼。
1.粗暴簡單辦法
直接定義一個(gè)變量,每次點(diǎn)擊過后等所有操作結(jié)束后釋放變量?;蚴褂胠oading防止用戶點(diǎn)擊
//* 部分代碼 <script> export default { methods: { onSubmit() { if (this.lock) return; this.lock = true; // const load = this.$loading(); this.$http.create().then((res) => { // do something this.lock = false; // load.close(); }).catch(() => { this.lock = false; // load.close(); }) }, }, } </script>
這種辦法簡單粗暴,但是每次需要防止重復(fù)點(diǎn)擊的地方,都要去關(guān)注lock或者loading的重置,總覺的很啰嗦。也沒辦法好好的抽離出來。(PS:能力有限,自己也沒有想到比較好的辦法在上層優(yōu)雅的封裝出來)
2.直接把loading放到http請求中去做,統(tǒng)一封裝方法
//* 部分代碼 ... let load; http.interceptors.request.use((config) => { load = Loading(); ... return config; }, error => { load.close(); return Promise.reject(error) }); http.interceptors.response.use((response) => { load.close(); ... return response; },error => { load.close(); return Promise.reject(error); });
這種辦法在實(shí)際中也用過了一段時(shí)間,一開始挺好用的,但是在后面自己弱網(wǎng)測試的時(shí)候發(fā)現(xiàn)也是會(huì)導(dǎo)致重復(fù)點(diǎn)擊的情況。而且在有些時(shí)候loading圖并不是所有請求都需要,還要去做個(gè)是否顯示loading的配置,這樣感覺http請求又笨重了,也沒有讓重復(fù)點(diǎn)擊功能抽離出來。
3.裝飾器方法
說到裝飾器,最經(jīng)典的應(yīng)用場景就是面向切片編程(AOP),《前端常用設(shè)計(jì)模式(1)--裝飾器(decorator)》juejin.im/post/5cb415… 做出了很棒的理解與應(yīng)用。得益于ES7和TS,裝飾器在Angular和react中都有很多案例,因?yàn)閂ue中Class不是必選,所以在Vue中很少看到使用裝飾器的,得益于官方有vue-class-component來使用Class進(jìn)行創(chuàng)建組件的方法,開始了自己的嘗試之路。
lock.js
export function lock(target, key, desc) { const fn = desc.value; //* 沒有使用箭頭函數(shù)是為了讓this能指回到vue,這樣就可以獲取到vue的data,從而做更多的事情,下面會(huì)講到 desc.value = async function() { if (this.$lock) return; this.$lock = true; await fn.apply(this).catch(() => { this.$lock = false; }); this.$lock = false; return target; }; }
index.vue
<template> <!-- do something --> </template> <script> import Vue from 'vue'; import Component from 'vue-class-component'; import { lock } from './lock'; @Component export default class extends Vue { @lock async onSubmit() { await this.$http.create(); // do something } } </script>
感覺這樣就完全抽離了重復(fù)點(diǎn)擊的功能(PS:好像是這樣的),也能獨(dú)立測試,想在哪里用就在哪里用。感覺不足的是,裝飾器里需要讓this重新指回vue才能獲取到vue的data
4.舉一反三
既然重復(fù)點(diǎn)擊可以從業(yè)務(wù)代碼中抽離出來,那我們提交表單的字段驗(yàn)證也就同樣可以抽離出來了。(PS:所有UI框架都有成熟的form表單驗(yàn)證組件,就當(dāng)我是瞎折騰)
validate.js
export function validate(target, key, desc) { const fn = desc.value; desc.value = async function () { const { name, phone, } = this.data; if (!name) { return confirm('請輸入您的姓名'); } if (name.length > 20) { return confirm('您的姓名不能超過20個(gè)字'); } if (!phone) { return confirm('請輸入您的電話'); } if (!((/^\d{11}$/.test(phone)))) { return confirm('請輸入11位的電話號碼'); } await fn.apply(this); return target; }; }
index.vue
<template> <!-- do something --> </template> <script> import Vue from 'vue'; import Component from 'vue-class-component'; import { validate } from './validate'; @Component export default class extends Vue { data = { name: '', phone: '', } @validate async onSubmit() { await this.$http.create(); // do something } } </script>
5.防抖方法(補(bǔ)充)
有小伙伴說可以使用防抖,個(gè)人覺得還是需要看場景,這里也就列出防抖的方法。
防抖方法是一個(gè)很好限制重復(fù)事件頻繁觸發(fā)的,經(jīng)常用在scroll、resize事件上,也可以嘗試用在重復(fù)點(diǎn)擊上面。但是如果點(diǎn)擊事件后需要有異步處理,單單使用防抖方法也會(huì)沒辦法限制弱網(wǎng)(PS:吐槽一下成都地鐵上移動(dòng)經(jīng)常網(wǎng)絡(luò)不好)下重復(fù)點(diǎn)擊的情況。如:防抖時(shí)間為1秒,但是請求花掉了2秒才返回?cái)?shù)據(jù)給前端進(jìn)行處理,中間產(chǎn)生了時(shí)間差,導(dǎo)致用戶有時(shí)間重復(fù)點(diǎn)擊。所以個(gè)人覺得還是需要配合其它辦法。同樣列出防抖的列子:
throttle.js
const throttle = function(fn, wait, scope) { clearTimeout(throttle.timer); throttle.timer = setTimeout(function() { fn.apply(scope); }, wait); };
index.vue
<template> <!-- do something --> </template> <script> export default { onSubmit() { throttle(() => { this.$http.create().then((result) => { // do something }); }, 1000); }, }; </script>
以上所述是小編給大家介紹的對于防止按鈕重復(fù)點(diǎn)擊的嘗試詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- 關(guān)于javascript中限定時(shí)間內(nèi)防止按鈕重復(fù)點(diǎn)擊的思路詳解
- Vue.js點(diǎn)擊切換按鈕改變內(nèi)容的實(shí)例講解
- JS實(shí)現(xiàn)的倒計(jì)時(shí)恢復(fù)按鈕點(diǎn)擊功能【可用于協(xié)議閱讀倒計(jì)時(shí)】
- js實(shí)現(xiàn)點(diǎn)擊按鈕復(fù)制文本功能
- JS實(shí)現(xiàn)的按鈕點(diǎn)擊顏色切換功能示例
- JS簡單實(shí)現(xiàn)點(diǎn)擊按鈕或文字顯示遮罩層的方法
- js記錄點(diǎn)擊某個(gè)按鈕的次數(shù)-刷新次數(shù)為初始狀態(tài)的實(shí)例
- js控制按鈕,防止頻繁點(diǎn)擊響應(yīng)的實(shí)例
- JS判斷鍵盤是否按的回車鍵并觸發(fā)指定按鈕點(diǎn)擊操作的方法
- js實(shí)現(xiàn)點(diǎn)擊按鈕彈出上傳文件的窗口
相關(guān)文章
javascript實(shí)現(xiàn)京東快遞單號的查詢效果
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)京東快遞單號的查詢效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11JavaScript搜索字符串并將搜索結(jié)果返回到字符串的方法
這篇文章主要介紹了JavaScript搜索字符串并將搜索結(jié)果返回到字符串的方法,涉及javascript中match方法操作字符串的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04js對字符串和數(shù)字進(jìn)行加法運(yùn)算的一些情況
這篇文章主要介紹了js對字符串和數(shù)字進(jìn)行加法運(yùn)算的一些情況,需要的朋友可以參考下2023-02-02深入理解JavaScript系列(9) 根本沒有“JSON對象”這回事!
寫這篇文章的目的是經(jīng)??吹介_發(fā)人員說:把字符串轉(zhuǎn)化為JSON對象,把JSON對象轉(zhuǎn)化成字符串等類似的話題,所以把之前收藏的一篇老外的文章整理翻譯了一下,供大家討論,如有錯(cuò)誤,請大家指出,多謝2012-01-01javascript宿主對象之window.navigator詳解
這篇文章主要為大家詳細(xì)介紹了javascript宿主對象之window.navigator,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09JS實(shí)現(xiàn)數(shù)組隨機(jī)排序的三種方法詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript中實(shí)現(xiàn)數(shù)組隨機(jī)排序的三種方式,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)或工作有一定參考價(jià)值,需要的可以參考一下2022-05-05JS數(shù)組去重常用方法實(shí)例小結(jié)【4種方法】
這篇文章主要介紹了JS數(shù)組去重常用方法,結(jié)合實(shí)例形式總結(jié)分析了4種常用的數(shù)據(jù)去重實(shí)現(xiàn)方法,涉及javascript數(shù)組的遍歷、判斷、追加等相關(guān)操作技巧,需要的朋友可以參考下2018-05-05javascript生成/解析dom的CDATA類型的字段的代碼
javascript生成/解析dom的CDATA類型的字段的代碼...2007-04-04