Vue 利用指令實(shí)現(xiàn)禁止反復(fù)發(fā)送請(qǐng)求的兩種方法
前端做后臺(tái)管控系統(tǒng),在某些接口請(qǐng)求時(shí)間過長的場(chǎng)景下,需要防止用戶反復(fù)發(fā)起請(qǐng)求。
假設(shè)某場(chǎng)景下用戶點(diǎn)擊查詢按鈕后,后端響應(yīng)需要長時(shí)間才能返回?cái)?shù)據(jù)。那么要規(guī)避用戶返回點(diǎn)擊查詢按鈕無外乎是讓用戶無法在合理時(shí)間內(nèi)再次點(diǎn)擊按鈕。實(shí)現(xiàn)方式也有好幾種:
1、在按鈕點(diǎn)擊發(fā)起請(qǐng)求后,彈個(gè)蒙層,顯示個(gè)loading,等請(qǐng)求數(shù)據(jù)返回了將蒙層隱藏掉。
2、在按鈕點(diǎn)擊發(fā)起請(qǐng)求后,將按鈕禁用掉,同樣等數(shù)據(jù)返回了將按鈕禁用解除。
以上是比較常見的2種方案。
實(shí)現(xiàn)上最簡單的肯定是在需要的頁面種在請(qǐng)求前和拿到數(shù)據(jù)后,單獨(dú)處理。這種方案優(yōu)點(diǎn)僅僅是簡單,但是每個(gè)需要處理的頁面都要單獨(dú)寫一串重復(fù)的代碼,哪怕利用mixin也要多不少冗余代碼。
如果是利用指令的方式僅僅需要在合適的地方加上個(gè)一條v-xxxx,其他都在指令的邏輯內(nèi)統(tǒng)一處理。
以第二種方式為例:
clickForbidden.js
let forbidClick = null;
export default {
bind(e) {
const el = e;
let timer = null;
forbidClick = () => {
el.disabled = true;
el.classList.add('is-disabled');
timer = setTimeout(() => {
el.disabled = false;
el.classList.remove('is-disabled');
}, 3000);
};
el.addEventListener('click', forbidClick);
},
unbind() {
document.removeEventListener('click', forbidClick);
},
};
指令的邏輯很簡單,當(dāng)按鈕插入到DOM節(jié)點(diǎn)后,添加一個(gè)監(jiān)聽click的事件,當(dāng)按鈕點(diǎn)擊后,就將按鈕禁用,并加上一個(gè)禁用樣式,并在3s后將該按鈕解除禁用。
再考慮請(qǐng)求,以axios為例:
api.js
import axios from 'axios';
export baseURL = 'xxxx';
const api = axios.create({
baseURL,<br data-filtered="filtered"> timeout: 3000,
});
/* 記錄當(dāng)前請(qǐng)求是否完成 */
window.currentResq = {
done: true,
config: {},
};
api.interceptors.request.use(function(config) {
clearTimeout(resqTimer);
window.currentResq = {
done: false,
config,
};
// 接口請(qǐng)求時(shí)長超過3s,則視為完成,不管請(qǐng)求結(jié)果成功或失敗
resqTimer = setTimeout(() => {
window.currentResq = {
done: true,
config: {},
};
}, 3000);
});
api.interceptors.response.use(function(response) {
const { config } = window.currentResq;
const { url, method, data } = response.config;
if (config.url === url && config.method === method && config.data === data) {
clearTimeout(resqTimer);
window.currentResq.done = true;
}
return response;
}, function (error) {
return error;
});
export default api;
用一個(gè)全局的currentResq來作為請(qǐng)求是否完成的標(biāo)志。在axios請(qǐng)求攔截器種,將當(dāng)前請(qǐng)求的數(shù)據(jù)記錄在currentResq中,并將done設(shè)置為false。在axios響應(yīng)攔截器中,約定url,method,data3個(gè)參數(shù)一樣時(shí),就是當(dāng)前currentResq中記錄的請(qǐng)求返回?cái)?shù)據(jù),并將done設(shè)置為true。
同樣的在指令邏輯中加入一個(gè)輪詢監(jiān)聽currentResq的done是否完成。
clickForbidden.js
let forbidClick = null;
export default {
bind(e) {
const el = e;
let timer = null;
forbidClick = () => {
el.disabled = true;
el.classList.add('is-disabled');
timer = setInterval(() => {
if (window.currentResq.done) {
clearInterval(timer);
el.disabled = false;
el.classList.remove('is-disabled');
}
}, 500);
};
el.addEventListener('click', forbidClick);
},
unbind() {
document.removeEventListener('click', forbidClick);
},
};
這樣就實(shí)現(xiàn)了只要在按鈕上加上了v-clickForbidden。按鈕點(diǎn)擊后就會(huì)被禁用,僅當(dāng)某個(gè)請(qǐng)求返回?cái)?shù)據(jù)或者3s后將按鈕的禁用解除。
現(xiàn)在僅僅考慮按鈕一次僅發(fā)送了一個(gè)請(qǐng)求的場(chǎng)景,在currentResq中也可以用一個(gè)數(shù)據(jù)來記錄請(qǐng)求。
總結(jié)
以上所述是小給大家介紹的Vue 利用指令實(shí)現(xiàn)禁止反復(fù)發(fā)送請(qǐng)求的兩種方法,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
相關(guān)文章
vue跳轉(zhuǎn)外部鏈接始終有l(wèi)ocalhost的問題
這篇文章主要介紹了vue跳轉(zhuǎn)外部鏈接始終有l(wèi)ocalhost的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Vue實(shí)現(xiàn)點(diǎn)擊顯示不同圖片的效果
這篇文章主要為大家詳細(xì)介紹了Vue實(shí)現(xiàn)點(diǎn)擊顯示不同圖片的效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
vue開發(fā)實(shí)現(xiàn)評(píng)論列表
這篇文章主要為大家詳細(xì)介紹了vue開發(fā)實(shí)現(xiàn)評(píng)論列表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
vue3.x項(xiàng)目中,出現(xiàn)紅色波浪線問題及解決
這篇文章主要介紹了vue3.x項(xiàng)目中,出現(xiàn)紅色波浪線問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03

