77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import Vue from 'vue';
|
|
import getOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor;
|
|
|
|
export interface Decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any> {
|
|
decorate(f: (...farg: FArgs) => any, ...args: TArgs): (...farg: FArgs) => TRet;
|
|
|
|
(...args: TArgs): (target, name: string | symbol, descriptor: TypedPropertyDescriptor<(...farg: FArgs) => FRet>) => void;
|
|
}
|
|
|
|
export function decorator<TArgs extends any[], FArgs extends any[], TRet extends any, FRet extends any>
|
|
(decorate: (f: (...farg: FArgs) => FRet, ...args: TArgs) => (...farg: FArgs) => TRet)
|
|
: Decorator<TArgs, FArgs, TRet, FRet> {
|
|
|
|
const factory = function (this: Decorator<TArgs, FArgs, TRet, FRet>, ...args: TArgs) {
|
|
return (target, name: string | symbol, descriptor: PropertyDescriptor) => {
|
|
descriptor.value = decorate(descriptor.value, ...args);
|
|
}
|
|
} as Decorator<TArgs, FArgs, TRet, FRet>;
|
|
factory.decorate = decorate;
|
|
|
|
return factory;
|
|
}
|
|
|
|
export const throttle = decorator(function (decorated, time: number) {
|
|
let timeout;
|
|
return function (this: any, ...args) {
|
|
if (typeof timeout === 'undefined') {
|
|
timeout = window.setTimeout(() => {
|
|
decorated.call(this, ...args);
|
|
timeout = undefined;
|
|
}, time);
|
|
}
|
|
}
|
|
});
|
|
|
|
export const debounce = decorator(function (decorated, time: number, max: number = time * 3) {
|
|
let timeout;
|
|
return function (this: any, ...args) {
|
|
if (typeof timeout !== 'undefined') {
|
|
window.clearTimeout(timeout);
|
|
}
|
|
|
|
timeout = window.setTimeout(() => {
|
|
timeout = undefined;
|
|
decorated.call(this, ...args);
|
|
}, time);
|
|
}
|
|
});
|
|
|
|
export const condition = decorator(function <Args extends any[], Ret extends any>(decorated: (...args: Args) => Ret, predicate: (...args: Args) => boolean) {
|
|
return function (this: any, ...args: Args) {
|
|
if (predicate(...args)) {
|
|
return decorated(...args);
|
|
}
|
|
}
|
|
});
|
|
|
|
// decorators.js
|
|
import { createDecorator } from 'vue-class-component'
|
|
|
|
export const notify = (name?: string) => createDecorator((options, key) => {
|
|
const symbol = Symbol(key);
|
|
|
|
if (typeof options.computed === 'undefined') {
|
|
options.computed = {};
|
|
}
|
|
|
|
options.computed[key] = {
|
|
get: function (this: Vue) {
|
|
return this[symbol];
|
|
},
|
|
set: function (this: Vue, value: any) {
|
|
this[symbol] = value;
|
|
this.$emit(name ? name : `update:${key}`, value);
|
|
}
|
|
}
|
|
}); |