Files
cz-web/src/directives/debounce.ts
2026-10-01 17:24:57 +08:00

35 lines
986 B
TypeScript

import type { Directive } from 'vue'
interface DebounceBinding {
handler: (...args: unknown[]) => void
delay?: number
}
type DebounceValue = DebounceBinding['handler'] | DebounceBinding
const listenerMap = new WeakMap<Element, EventListener>()
function normalize(value: DebounceValue): DebounceBinding {
return typeof value === 'function' ? { handler: value } : value
}
const debounce: Directive<Element, DebounceValue> = {
mounted(el, binding) {
const { handler, delay = 300 } = normalize(binding.value)
let timer: ReturnType<typeof setTimeout> | 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