v-debounce和v-throttle的实现
const debouce = function (func, wait, immdiate) {
if (typeof func !== "function") return;
if (typeof wait !== "number") {
if (typeof wait === "boolean") {
immdiate = wait;
}
}
if (typeof wait === "undefined") {
wait = 500;
}
if (typeof immdiate === "undefined") {
immdiate = false;
}
let timer = null,
result;
return function proxy(...arg) {
let self = this;
let now = immdiate && !timer ? true : false;
clearTimeout(timer);
timer = setTimeout(function () {
timer = null;
result = !immdiate ? func.call(self, ...arg) : null;
}, wait);
result = now ? func.call(self, ...arg) : null;
return result
};
};
const throttle = function throttle(func, interval) {
if (typeof func !== "function") return;
if (typeof interval === "undefined") {
interval = 500;
}
let pre = 0,
timer = null;
return function (...args) {
let now = new Date(),
self = this;
let remaining = interval - (now - pre);
if (remaining <= 0) {
clearTimeout(timer);
timer = null;
pre = now;
func.call(self, ...args);
} else if (!timer) {
timer = setTimeout(() => {
clearTimeout(timer);
timer = null;
pre = new Date();
func.call(self, ...args);
}, remaining);
}
};
};
let config = {
bind(el, binding) {
let wait = 200,
val = binding.value,
immediate = false,
func,
type = 'click',
params = [],
handle = binding.name === 'debounce' ? debouce : throttle
if (val == null) return
if (typeof val !== 'function' && typeof val !== 'object') return
if (binding.arg) {
wait = + binding.arg;
}
if (binding.modifiers && binding.modifiers.immdiate) immediate = binding.modifiers.immdiate;
if (typeof val === 'function') {
func = val;
}
if (typeof val === 'object') {
func = val.func || function () { };
type = val.type || 'click';
params = val.params || []
}
el.$type = type;
el.$handle = handle(function proxy(arg) {
return func.call(this, ...params.concat(arg))
}, wait, immediate)
el.addEventListener(el.$type, el.$handle)
},
unbind(el) {
el.removeEventListener(el.$type, el.$handle)
}
}
Vue.directive('debounce', config)
Vue.directive('throttle', config)
使用
<template>
<div id="app">
<button
v-debounce:3000.immdiate="{
func: fn,
params: [2, 3],
type: 'click',
}"
>
点我呀
</button>
<button
v-throttle:1000="{
func: fn,
params: [10, 20],
}"
>
点我啊~~
</button>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
};
},
methods: {
fn(a, b) {
console.log(a, b);
},
},
};
</script>