import Vue from 'vue'
const preventReClick = Vue.directive('preventReClick', {
inserted: function(el, binding) {
el.addEventListener('click', () => {
if (!el.disabled) {
el.disabled = true
setTimeout(() => {
el.disabled = false
}, binding.value || 3000) // 傳入綁定值就使用,默認3000毫秒內不可重複觸發
}
})
}
})
export { preventReClick }
複製代碼
import preventReClick from './plugins/directives.js' //防屢次點擊,重複提交複製代碼
// 指定延遲1000ms <el-button size="small" type="primary" @click="handleSave()" v-preventReClick="1000">保 存</el-button> // 默認延遲時間3000 <el-button size="small" type="primary" @click="handleSave()" v-preventReClick>保 存</el-button> 複製代碼
可使用 CancelToken.source
工廠方法建立 cancel token,像這樣:javascript
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// 處理錯誤
}
});
// 取消請求(message 參數是可選的)
source.cancel('Operation canceled by the user.');
複製代碼
還能夠經過傳遞一個 executor 函數到 CancelToken
的構造函數來建立 cancel token:html
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// executor 函數接收一個 cancel 函數做爲參數
cancel = c;
})
});
// 取消請求
cancel();
複製代碼
Note : 可使用同一個 cancel token 取消多個請求vue
import axios from 'axios'
const pending = [] // 聲明一個數組用於存儲每一個ajax請求的隊列
const cancelToken = axios.CancelToken // 初始化取消請求的構造函數
let arr = [] // 區分是請求仍是響應的頭部
/** * @param {請求體信息} config * @param {直接執行的cancel函數,執行便可取消請求} f */
const removePending = (config, f) => {
arr = config.url.split(window.g.apiUrl)
arr = arr[arr.length - 1]
const flagUrl = arr + '&' + config.method // 每次請求存儲在請求中隊列的元素關鍵值
// 當前請求存在隊列中
if (pending.indexOf(flagUrl) !== -1) {
if (f) {
f() // 取消請求
} else {
pending.splice(pending.indexOf(flagUrl), 1) // 取消函數不存在,則從隊列中刪除該請求
}
} else {
// 當前請求不在隊列中
if (f) {
pending.push(flagUrl)
}
}
}
// 添加請求攔截器
axios.interceptors.request.use(
config => {
if (config.method === 'post') {
config.cancelToken = new cancelToken(c => {
removePending(config, c)
})
}
return config
},
error => {
return Promise.reject(error)
}
)
axios.interceptors.response.use(response => {
if (response.config.method === 'post') {
removePending(response.config)
}
})
複製代碼
我推薦用主動查詢狀態的方式(A、B,jQuery 爲例)或工具函數的方式(C、D)來去除重複操做,並提供一些例子做爲參考:java
module.submit = function() {
if (this.promise_.state() === 'pending') {
return
}
return this.promise_ = $.post('/api/save')
}
複製代碼
module.submit = function() {
if (this.promise_.state() === 'pending') {
this.promise_.abort()
}
// todo
}
複製代碼
好比某些應用的條目中,有一些進行相似「喜歡」或「不喜歡」操做的二態按鈕。若是按下後不當即給出反饋,用戶的目光焦點就可能在那個按鈕上停頓許久;若是按下時即時切換按鈕的狀態,再在程序上用 abort 來實現積極的提交,這樣既能提升用戶體驗,還能下降服務器壓力,皆大歡喜。ios
module.submit = throttle(150, function() {
// todo
})
複製代碼
若是客戶發送每隔100毫秒發送過來10次請求,此模塊將只接收其中6個(每一個在時間線上距離爲150毫秒)進行處理。
這也是解決查詢衝突的一種可選手段,好比以知乎草稿舉例,仔細觀察能夠發現:
編輯器的 blur 事件會當即觸發保存;
保存按鈕的 click 事件也會當即觸發保存;
可是存在一種狀況會使這兩個事件在數毫秒內連續發生——當焦點在編輯器內部,而且直接去點擊保存按鈕——這時用 throttle 來處理是可行的。
另外還有一些事件處理會很頻繁地使用 throttle,如: resize、scroll、mousemove。git
module.submit = debounce(150, function() {
// todo
})
複製代碼
仍是以知乎草稿舉例,當在編輯器內按下 ctrl + s 時,能夠手動保存草稿;若是你連按,程序會表示不理解爲何你要連按,只有等你放棄連按,它纔會繼續。github