vasille
Version:
The same framework which is designed to build bulletproof frontends (core library).
71 lines (70 loc) • 1.83 kB
JavaScript
import { Reference } from "./reference.js";
import { IValue } from "../core/ivalue.js";
/**
* Bind some values to one expression
* @class Expression
* @extends IValue
*/
export class Expression extends IValue {
/**
* The array of value which will trigger recalculation
* @type {Array}
*/
values;
/**
* Cache the values of expression variables
* @type {Array}
*/
valuesCache;
/**
* Expression will link different handler for each value of the list
*/
linkedFunc = [];
/**
* The buffer to keep the last calculated value
*/
sync;
/**
* Creates a function bounded to N values
*/
constructor(func, values, ctx) {
super();
const handler = (i) => {
/* istanbul ignore else */
if (typeof i === "number") {
this.valuesCache[i] = this.values[i]?.V;
}
this.sync.V = func.apply(this, this.valuesCache);
};
this.valuesCache = values.map(item => item?.V);
this.sync = new Reference(func.apply(this, this.valuesCache));
let i = 0;
values.forEach(value => {
const updater = handler.bind(this, Number(i++));
this.linkedFunc.push(updater);
value?.on(updater);
});
this.values = values;
ctx?.bind(this);
}
get V() {
return this.sync.V;
}
set V(value) {
this.sync.V = value;
}
on(handler) {
this.sync.on(handler);
}
off(handler) {
this.sync.off(handler);
}
destroy() {
for (let i = 0; i < this.values.length; i++) {
this.values[i]?.off(this.linkedFunc[i]);
}
this.values.splice(0);
this.valuesCache.splice(0);
this.linkedFunc.splice(0);
}
}