v-throttle
Vue 自定义指令 v-throttle 旨在实现一个“节流”功能,节流意味着在一段时间内只触发一次函数,而不是在连续触发事件时阻止事件处理函数的执行。
这里使用了闭包来存储上一次触发事件的时间,并在距离上次触发超过一定时间后才执行回调函数:
javascript
Vue.directive('throttle', {
bind: (el, binding, vnode) => {
let throttleTime = binding.value || 2000; // 节流时间,如果用户未设置则默认为2s
let lastRun = 0;
el.addEventListener('click', (event) => {
const now = new Date().getTime();
if (now - lastRun >= throttleTime) {
// 如果距离上次执行的时间超过了节流时间,则执行方法
lastRun = now;
// 触发事件绑定的方法
vnode.context[vnode.data.on.click](event);
}
}, true);
},
});
// 在模板中使用自定义指令
<button @click="sayHello" v-throttle="1500">提交</button>
在上面的代码中,我使用了 vnode.context[vnode.data.on.click] 来调用绑定在 @click 上的方法。这通常是一个合理的做法,因为它能够确保我们调用的是 Vue 实例上的正确方法。但是,请注意,如果 sayHello 方法不是定义在 Vue 实例上,而是定义在某个组件的方法中,那么这种方法可能不起作用。
此外,我还添加了一个 throttleTime 的默认值,并允许用户通过指令值(v-throttle="1500")来覆盖这个默认值。
最后,true 作为第三个参数传递给 addEventListener 是为了在捕获阶段处理事件,这通常不是必要的,除非你有特定的理由需要在捕获阶段处理点击事件。在大多数情况下,冒泡阶段就足够了。
如果你想要的是防抖(debounce)效果(即,在一段时间内多次触发事件后,只在最后一次触发后的一段时间内执行一次方法),则需要使用不同的逻辑。
v-debounce
要实现防抖(debounce)效果的 Vue 自定义指令,你可以使用闭包来包裹一个定时器,确保在指定的等待时间内多次触发事件时,只有最后一次触发后经过指定时间才会执行回调函数。以下是防抖自定义指令的实现:
Vue.directive('debounce', {
bind: function (el, binding, vnode) {
let debounceTime = binding.value || 2000; // 防抖时间,用户若未设置则默认为2s
let timer = null;
// 封装防抖函数
function debounceHandler(event) {
if (timer) {
clearTimeout(timer); // 清除之前的定时器
}
timer = setTimeout(function () {
// 在防抖时间结束后执行回调函数
vnode.context[vnode.data.on.click](event);
timer = null; // 执行后清除定时器
}, debounceTime);
}
// 为元素添加事件监听器
el.addEventListener('click', debounceHandler);
// 当元素卸载时,清除定时器
el._debounceHandler = debounceHandler;
vnode.context.$once('hook:beforeDestroy', function () {
el.removeEventListener('click', el._debounceHandler);
if (timer) {
clearTimeout(timer);
}
});
},
});
// 在模板中使用自定义指令
<button @click="sayHello" v-debounce="1500">提交</button>
在这个例子中,我们定义了一个 debounceHandler
函数,它使用 setTimeout
来实现防抖逻辑。当点击事件被触发时,如果定时器 timer
已经存在,我们就清除它,并设置一个新的定时器。当定时器结束时,我们执行绑定在 @click
上的方法。
此外,我们还为元素添加了一个 _debounceHandler
属性来存储防抖处理函数,并在组件销毁前(beforeDestroy
钩子)移除事件监听器并清除定时器,以避免内存泄漏。
注意,在实际应用中,你可能需要根据具体的场景和需求来调整防抖逻辑,比如考虑在防抖期间是否允许执行回调,或者是否需要在防抖期间阻止事件的进一步传播等。