前言
截至目前,一线大厂常用的6大vue自定义指令中,我们已经学习实现了2个了,今天我们一起来看一下第三个常用的自定义指令防抖v-debounce。
关于javascript中是如何实现防抖,这里不再过多赘述,感兴趣的小伙伴可以查看这篇web前端高级JavaScript - 函数的防抖和节流文章了解更多。本篇文章主要介绍如何实现一个防抖的自定义指令,下面我们就来分析一下大体实现思路。
思路分析
- 我们知道一般情况下,防抖函数会接收3个参数:一个是防抖函数中要执行的具体函数func,一个是等待的时间wait,还有一个就是immediate标识立即执行还是最后执行。
之前学习vue自定义指令时我们已经知道:指令等号后面值会作为参数传递给指令函数,但是等号后面只有一个值,而我们要传递是3个值甚至更多,怎么办,其实也简单,我们只需要把要传递的参数拼成一个对象传递就可以了。这样传多少个参数都不是问题- 另外像wait和immediate这两个参数算是特殊参数,为什么这么说呢?wait是设置防抖时间的而immediate是作为标识的。这个时候冒号和修饰符就派上用场了。我们在使用vue指令的时候,在指令的后面可以跟一个冒号和一个值,而这个值也会被传给指令函数,并在函数中通过binding.arg或者这个值。同时指令后面还可以接修饰符,类似v-xxx.yyy,点后面的就是修饰符,在指令函数中通过binding.modifier.yyy获取该指令(一般是true或false值)
- 通过上面的分析,其中的两个参数我们已经通过冒号和修饰符的形式传递了,那么就只剩下一个函数了,这个时候我们完全可以不用传递对象而是直接将函数传给指令即可。所以这里就出现了两种情况,一种是传递了一个对象,还有一种是只穿一个函数。所以后面我们写代码时应该有所区分,如果是函数直接执行,如果是对象则需要解析出对象中的值。
- 另外为了让我们的自定义指令更灵活更通用,我们还需要做如下处理
- 在指令函数中再额外接收一个type参数,用来标识是什么类型的防抖,比如click或scroll等,这个可以自由选择
- 同时也接收一个额外的params参数。想想如果我们传递给指令的函数也需要其它参数呢,这时仍然可以通过外面以对象属性的形式进行传递
- 最后就是除了函数是必须要传的参数以外,其它几个参数可以传也可以不传,所以我们需要为这些除了func以外的其它参数设置默认值。
- 通过上面的思路分析,我想我们的防抖基本上已经差不多了。接下来就让我们来一起实践一下。
防抖v-debounce自定义指令代码
function debounce(func, wait = 300, immediate = true){
let timer = null;
return function anonymouse(...params){
clearTimeout(timer);
let now = immediate && !timer;
timer = setTimeout(() => {
timer = null;
!immediate ? func.call(this, ...params) : null;
},wait);
now ? func.call(this, ...params) : null;
}
}
const app = createApp();
app.directive("debounce",{
beforeMount(el,binding){
let val = binding.value,//获取指令传递的参数
wait = 500,//wait默认500毫秒
immidiate = false,
type = 'click',
params = [],
func
if(val == null) return;//如果没有传递任何参数则什么也不做
if(typeof val !== 'object' && typeof val !== 'function') return ;//如何传递的参数既不是对象也不是函数则也什么都不做
if(binding.arg) wait = +binding.arg;//获取冒号后面的参数
if(binding.modifiers && binding.modifiers.immediate) immediate = binding.modifiers.immediate;//获取修饰符
if(typeof val === 'function') func = val;//如果传递的是函数则直接赋给func
if(typeof val === 'object'){
//如果是对象则对对象进行解析
func = val.func || function(){
};
type = val.type || 'click';
params = val.params || [];
}
el.$type = type;
//此步操作多定义了一个proxy函数目的是可以给func传递参数,同时保证func中的this指向
el.$handle = debounce(function proxy(...args){
return func.call(this, ...params.concat(args));
},wait, immediate);
el.addEventListener(el.$type, el.$handle);
},
unmounted(el){
el.removeEventListener(el.$type, el.$handle);
}
});
总结
如此我们便实现了一个防抖的自定义指令,该指令相较于前两个指令有些复杂,涉及到的代码也是有点多的。但比起前两个来说也是更常用的。下篇文章中我们将一起研究下一个常用节流自定义指令。
好了本文就介绍到这里,有任何问题欢迎指正。同时喜欢的小伙伴欢迎点赞留言加关注哦!