概念
由于目前做的项目登录这块需要做单点登录,但是频繁点击登录按钮,就会出现刚登录上去提示“您的账号在别处登录”,然后被测试提了一个bug。怎么修复了?可以在登录时加节流,由此想着可以封装一下公共的防抖节流的方法。
防抖和节流其实我们在工作中经常会遇到,在这里简单对其概念做下简单描述:
- 防抖: 触发事件在一定时间内只执行一次,如果这段时间内又触发了,则会重新计算函数执行时间
- 节流:连续触发事件但在一定时间内只执行一次的函数
知道了概念以后,我们可以简单封装一下我们自己的防抖节流函数
手写防抖
知道了基本概念,手动实现一下防抖函数
/**
* 防抖的函数
* @param {*} func 要执行的函数
* @param {*} await 等待时间
* @param {*} immidate 是否立即执行, 默认falseß
*/
function debounce(func, await, immidate = false){
let timer = null
let debounce;
debounce = function() {
//this指向问题
let context = this;
//拿到参数
let args = [...arguments];
clearTimeout(timer);
if(immidate){
let callNow = !timer;
timer = setTimeout(()=>{
timer = null;
}, await)
//立即执行
callNow && func.apply(context, args);
} else {
timer = setTimeout(()=>{
func.apply(context, args);
}, await)
}
}
//取消防抖函数
debounce.cancal = ()=>{
clearTimeout(timer);
timer = null;
}
return debounce
}
手写节流
/**
* 节流函数
* @param {*} func 要执行的函数
* @param {*} await 每隔多长时间执行
*/
function throttle(func, await){
let context, args;
let previous = 0; //之前的时间戳
return function(){
([context, args] = [this, arguments])
let now = new Date().valueOf(); //获取当前的时间戳
if(now-previous>await){
func.apply(context, args);
old = now;
}
}
}
vue指令板
在实际情况中,防抖和节流的应用场景是非常多的。在vue项目中,我们可以将写好的方法挂载到vue原型上,这样的话整个项目无需再引入,可以全局使用。除此之外,我们还可以注册一个全局的指令,利用指令实现防抖节流的作用。
自定义指令的钩子函数和使用方法参考官网: 自定义指令官网地址
Vue.directive('throttle', {
inserted: function(el, binding) {
let timer;
el.addEventListener("click", () => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
binding.value();
}, 1000);
});
}
})