场景
1.保存提交按钮不小心点击了多次。
2.由于服务器请求时间过长等原因点击事件没有及时响应又点击了一次,造成数据的重复提交和保存,数据的异常。
3.resize、scroll,输入框内容校验等频繁操作。
原因
由于axios提交数据为异步提交,点击提交按钮是通过xmlhttprequest向后端发送异步请求,发送请求后后端返回数据需要时间处理,如果第一次点击的请求尚未完成,又接二连三地提交了几次,同时后面发送的请求都被后台处理了,这种情况如果是读取数据不会有太大影响,但是涉及到数据提交保存或者提交之后多表数据处理就麻烦了,而且此类现象造成的数据都不正常,所以此种情况务必要避免。
解决方法
一.防抖
原理:当第一次触发点击事件时,不会立即执行接口,会等待监听一段时间,若在这段时间没有再次触发该事件,等待时间过后就执行接口。倘若等待时间期间监听到又点击了一次,等待时间随即重置,从最后一次点击事件开始再重新等待这段时间,等待结束后再执行接口。
步骤:
1.创建防抖全局js方法
// debounce.js
export const debounce = (() => {
let timer = null
return (callback, wait) => {
clearTimeout(timer)
timer = setTimeout(callback, wait)
}
})()
2、具体引用
// test.vue
<script>
import { debounce } from "./debounce"
export default {
name: 'test',
data () {
return {}
},
methods: {
getMovieName (e) {
debounce(() => {
console.log("防抖成功")
}, 1000)
}
}
}
</script>
二.节流
原理:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
步骤:
1.创建节流全局js方法
/**
* 节流原理:在一定时间内,只能触发一次
*
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
* @return null
*/
let timer, flag;
const throttle = function(func, wait, immediate) {
if (immediate) {
if (!flag) {
flag = true;
// 如果是立即执行,则在wait毫秒内开始时执行
typeof func === 'function' && func();
timer = setTimeout(() => {
flag = false;
}, wait);
}
} else {
if (!flag) {
flag = true
// 如果是非立即执行,则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false
typeof func === 'function' && func();
}, wait);
}
}
};
2.具体引用
// 点赞、取消点赞
this.$util.throttle(this.likeCountDelete, 250, true)
缺点:若是现象2的情况,第一次请求返回时间超过等待的时间,此时再次点击就会再次调用事件接口,造成数据的重复异常
三.按钮禁用控制或者loading
原理:当第一次点击按钮进入事件,按钮状态变为禁用状态,或者打开loading函数进行等待,当请求返回后台数据后按钮再恢复至可点击状态或者loading关闭
// 按钮
<el-button @click="save" :disabled="disabledFlag">保 存</el-button>
save() {
// 调用接口之前禁用按钮,防止多次点击调用接口
this.disabledFlag = true
// 或者打开loading等待
this.loading.show()
// 调用接口进行添加填报数据
api.save({ id: this.id }).then(res => {
// 接口返回后
this.disabledFlag = false
this.loading.hide()
this.$message({
type: 'success',
message: "保存成功!"
})
}).catch(() => {
this.disabledFlag = false
this.loading.hide()
})
}