import type { Directive } from 'vue' interface DebounceBinding { handler: (...args: unknown[]) => void delay?: number } type DebounceValue = DebounceBinding['handler'] | DebounceBinding const listenerMap = new WeakMap() function normalize(value: DebounceValue): DebounceBinding { return typeof value === 'function' ? { handler: value } : value } /** v-debounce 防抖点击:v-debounce="fn" 或 v-debounce="{ handler: fn, delay: 500 }" */ const debounce: Directive = { mounted(el, binding) { const { handler, delay = 300 } = normalize(binding.value) let timer: ReturnType | null = null const listener: EventListener = () => { if (timer !== null) clearTimeout(timer) timer = setTimeout(() => handler(), delay) } listenerMap.set(el, listener) el.addEventListener('click', listener) }, unmounted(el) { const listener = listenerMap.get(el) if (listener) el.removeEventListener('click', listener) listenerMap.delete(el) }, } export default debounce