update
This commit is contained in:
57
src/utils.ts
57
src/utils.ts
@@ -1,3 +1,5 @@
|
||||
import { effectScope, type EffectScope } from "vue";
|
||||
|
||||
export function isPosInt(maybePosInt: number): boolean {
|
||||
return (maybePosInt | 0) === maybePosInt && maybePosInt > 0;
|
||||
}
|
||||
@@ -9,4 +11,57 @@ export function greatestCommonDivisor(a: number, b: number): number {
|
||||
a = temp;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
export class Bound {
|
||||
constructor() {
|
||||
for (const propertyKey of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
|
||||
// @ts-ignore
|
||||
const method = this[propertyKey];
|
||||
if (method instanceof Function) {
|
||||
// @ts-ignore
|
||||
this[propertyKey] = (method as Function).bind(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a constructor for a class that may contain vue reactive primitives, setting up an effect scope to capture
|
||||
* all effects, assigning a destroy function that will stop the effect scope and clean up effects.
|
||||
*
|
||||
* Wrapped classes containing reactive effects can be easily used without tying their lifetimes to a component instance
|
||||
* or the global application. This is effectively the equivalent of heap allocation instead of stack allocation.
|
||||
*
|
||||
* Advantages:
|
||||
* - less boilerplate (no need to remember to return all public methods and properties from a composable)
|
||||
* - makes it possible to manange reactive lifetimes that are entirely independent of UI state, such as objects that
|
||||
* are constantly instantiated and destroyed that manage their own reactive states, that need to be referenced
|
||||
* globally by multiple parts of a complex UI.
|
||||
* - The class syntax makes it easy to reference properites and functions before their declaration, avoiding annoying
|
||||
* forward declarations.
|
||||
*/
|
||||
export class EffectScoped {
|
||||
private effectScope?: EffectScope;
|
||||
|
||||
/**
|
||||
* Creates an effectscoped version of the class
|
||||
*/
|
||||
static asScoped<C extends new(...args: any[]) => EffectScoped>(this: C, ...args: ConstructorParameters<C>): InstanceType<C> {
|
||||
const scope = effectScope(true);
|
||||
const instance = scope.run(() => new this(...args)) ?? null;
|
||||
if (instance === null) {
|
||||
throw new Error(`Failed to instantiate class ${ this.constructor.name }.`);
|
||||
}
|
||||
instance.effectScope = scope;
|
||||
return instance as InstanceType<C>;
|
||||
}
|
||||
|
||||
onDestroy() {}
|
||||
|
||||
destroy() {
|
||||
this.onDestroy();
|
||||
this.effectScope?.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user