截至目前,一线大厂常用的6大vue自定义指令中,我们已经学习实现了3个了,而其中上一篇
一线大厂常用的六大vue自定义指令合集之防抖v-debounce中的自定义防抖指令与我们今天要学习的节流自定义指令除了函数不一样,其它的基本上是一模一样。下面让我们一起来揭开它的面纱吧!
关于javascript中是如何实现节流,这里不再过多赘述,感兴趣的小伙伴可以查看这篇web前端高级JavaScript - 函数的防抖和节流文章了解更多。本篇文章主要介绍如何实现一个节流的自定义指令,下面我们就来分析一下大体实现思路。
- 节流函数一般会接收2个参数:一个是节流函数中要执行的具体函数func,另一个则是节流等待的时间wait。
同样需要传递多个参数给指令函数时,我们可以组装一个对象一起传递- wait参数仍然可以以冒号的形式进行传递
- 对于指令函数体内接收到的参数进行判断处理:如果是函数直接传给节流函数,如果是对象则需对对象进行解析拆分。
- 另外还是为了让我们的自定义指令更灵活更通用,我们仍然需要在指令函数中再额外接收一个type和一个params参数,分别用来标识是什么类型的节流和节流函数所需的参数
- 最后就是除了函数以外的其它参数均需设置默认值。
- 最后让我们把节流的完整代码来实现一下
function throttle(func, wait){ let timer = null, previous = 0; return function anonmouse(...params){ let now = new Date(), remaining = wait - (now - previous); if(remaining <= 0){ previous = now; clearTimeout(timer); timer = null; func.call(this, ...params); }else if(!timer){ timer = setTimeout(() => { timer = null; previous = new Date(); func.call(this, ...params); }, remaining); } } } const app = createApp(); app.directive("throttle",{ beforeMount(el,binding){ let val = binding.value,//获取指令传递的参数 wait = 500,//wait默认500毫秒 type = 'click', params = [], func if(val == null) return;//如果没有传递任何参数则什么也不做 if(typeof val !== 'object' && typeof val !== 'function') return ;//如何传递的参数既不是对象也不是函数则也什么都不做 if(binding.arg) wait = +binding.arg;//获取冒号后面的参数 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 = throttle(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); } });
如此我们便实现了一个节流的自定义指令,通过上面的分析和实现不难发现:其实防抖和节流基本上是一样的,所以其实如果想进一步完善这两个指令还可以将一些公共部分提出来,甚至是防抖还是节流也可以通过参数传递来实现。有兴趣的小伙伴可以试一下。
好了本文就介绍到这里,有任何问题欢迎指正。同时喜欢的小伙伴欢迎点赞留言加关注哦!