记录所学,检验自己的掌握程度。
我们会遇到这样的场景,
一个按钮,正常逻辑是点击一次,等待接口返回数据,进行接下来的处理,
不小心一下次点了两次,就可能会造成提交两次的情况,接下来有了一堆bug,,,
我们来用防抖来尽可能的规避掉这个问题:
// 接收三个参数 1 需要防抖的函数
// 2 第一次点击到第二次点击的间隔小于 多久 会触发防抖
// 3 第一次是否需要立即执行函数
function debounce(fn, wait,...args){
let timer;
return function(){
let context = this;
/* 使用闭包 来判断当前微任务队列是否有 fn
在微任务队列 如果有就清除微任务队列的 fn */
if(timer) clearTimeout(timer);
// 在微任务队列添加事件
timer = setTimeout(() => {
fn.call(context, args);
}, wait || 1000);
}
}
复制代码
顺便整下节流
节流一个我能理解的应用场景就是 图片懒加载
判断图片是否处于可视区域,
这里先不实现,仅实现个节流的函数
和防抖类似
时间戳版本
function throttle(fn, wait,args){
/*
基本思路是:当调用节流函数时返回一个函数,
这个时候记录了一个时间戳(prev),
当触发节流函数返回的函数的时候,记录另一个时间戳,
当两个时间戳大于我们定义的 wait的时候,
就调用函数,这个时候改变prev函数
*/
let prev = Date.now();
return function(){
let context = this;
let current = Date.now();
if(current - prev >= wait){
fn.call(context, [...arguments]);
// 改变prev的值 重新计时
prev = current;
}
}
}
复制代码
定时器版本
function throttle (func, wait, ...args) {
let timeout;
/*
思路:当timeout有值的时候,就忽略掉func函数的处理
定时器到时,调用回调函数的时候,timout =null,调用func,
为第一次调用函数,
当timeout == null的时候,就启动一个定时器,
微任务队列中注入函数func,
如此循环往复
*/
return function(){
const context = this;
if(!timeout){
timeout = setTimeout(() => {
timeout = null;
func.apply(context,args);
},wait)
}
}
}
复制代码
推荐阅读 防抖和节流原理分析,我的这篇记录也是由此而来,
把防抖和节流,做成Vue自定义指令,版本:2.6.11
同时来回忆下Vue官网自定义指令
// 防抖指令
const debounce = {
inserted:function(el, binding){
console.log(el, binding);
let timer;
let fn = binding.value;
let opts = binding.arg[0],time = binding.arg[1] || 1000
el.addEventListener('click',function(){
if(timer) clearTimeout(timer);
timer = setTimeout(() => {
fn(opts);
}, time);
})
}
}
export default debounce;
复制代码
PS: 如果仅仅是为防止按钮多次点击,有比上述防抖指令更优雅的解决方案,
比如:在指令里边直接令按钮不可点击,当逻辑处理好后,放开按钮,
这里防抖仅仅只是其中一种,~~
节流指令
const throttle = {
inserted:function(el, binding){
let prev = Date.now();
let fn = binding.value;
let opt = binding.arg[0],time = binding.arg[1] || 1000
el.addEventListener('click',function(){
let current = Date.now();
if(current - prev > time){
fn(opt);
prev = current;
}
})
}
}
复制代码
使用
// iview的框架
<Button v-debounce:[[arg1,2000]]="logFunc" type="primary">连续点击</Button>
复制代码
推荐阅读 分享8个非常实用的Vue自定义指令
记录所学,加深自己的理解,欢迎指出错误之处~~
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END