vuecssuiant-designantdreactantantd-vueenterprisefrontendui-designvue-antdvue-antd-uivue3vuecomponent
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
2.3 KiB
89 lines
2.3 KiB
// copy from https://github.dev/vueuse/vueuse |
|
|
|
import type { Ref, WatchOptions, WatchStopHandle } from 'vue'; |
|
import { unref, watch } from 'vue'; |
|
|
|
type MaybeRef<T> = T | Ref<T>; |
|
|
|
type Fn = () => void; |
|
|
|
export type FunctionArgs<Args extends any[] = any[], Return = void> = (...args: Args) => Return; |
|
|
|
export interface FunctionWrapperOptions<Args extends any[] = any[], This = any> { |
|
fn: FunctionArgs<Args, This>; |
|
args: Args; |
|
thisArg: This; |
|
} |
|
|
|
export type EventFilter<Args extends any[] = any[], This = any> = ( |
|
invoke: Fn, |
|
options: FunctionWrapperOptions<Args, This>, |
|
) => void; |
|
|
|
const bypassFilter: EventFilter = invoke => { |
|
return invoke(); |
|
}; |
|
/** |
|
* Create an EventFilter that debounce the events |
|
* |
|
* @param ms |
|
*/ |
|
export function debounceFilter(ms: MaybeRef<number>) { |
|
let timer: ReturnType<typeof setTimeout> | undefined; |
|
|
|
const filter: EventFilter = invoke => { |
|
const duration = unref(ms); |
|
|
|
if (timer) clearTimeout(timer); |
|
|
|
if (duration <= 0) return invoke(); |
|
|
|
timer = setTimeout(invoke, duration); |
|
}; |
|
|
|
return filter; |
|
} |
|
export interface DebouncedWatchOptions<Immediate> extends WatchOptions<Immediate> { |
|
debounce?: MaybeRef<number>; |
|
} |
|
|
|
interface ConfigurableEventFilter { |
|
eventFilter?: EventFilter; |
|
} |
|
/** |
|
* @internal |
|
*/ |
|
function createFilterWrapper<T extends FunctionArgs>(filter: EventFilter, fn: T) { |
|
function wrapper(this: any, ...args: any[]) { |
|
filter(() => fn.apply(this, args), { fn, thisArg: this, args }); |
|
} |
|
|
|
return wrapper as any as T; |
|
} |
|
export interface WatchWithFilterOptions<Immediate> |
|
extends WatchOptions<Immediate>, |
|
ConfigurableEventFilter {} |
|
// implementation |
|
export function watchWithFilter<Immediate extends Readonly<boolean> = false>( |
|
source: any, |
|
cb: any, |
|
options: WatchWithFilterOptions<Immediate> = {}, |
|
): WatchStopHandle { |
|
const { eventFilter = bypassFilter, ...watchOptions } = options; |
|
|
|
return watch(source, createFilterWrapper(eventFilter, cb), watchOptions); |
|
} |
|
|
|
// implementation |
|
export default function debouncedWatch<Immediate extends Readonly<boolean> = false>( |
|
source: any, |
|
cb: any, |
|
options: DebouncedWatchOptions<Immediate> = {}, |
|
): WatchStopHandle { |
|
const { debounce = 0, ...watchOptions } = options; |
|
|
|
return watchWithFilter(source, cb, { |
|
...watchOptions, |
|
eventFilter: debounceFilter(debounce), |
|
}); |
|
}
|
|
|