@winged/core
Version:
Morden webapp framekwork made only for ts developers. (UNDER DEVELOPMENT, PLEASE DO NOT USE)
67 lines (58 loc) • 1.82 kB
text/typescript
import { ModificationTree } from '../types'
type WatcherCallback = (modificationTree: ModificationTree) => void
export abstract class Observable {
private static idCounter = 0
public readonly _observableId = ++Observable.idCounter
protected _watchedTargets: {
[id: string]: { target: Observable, watcherCount: number }
} = {}
protected _watchers: Array<{
context: any;
callback: WatcherCallback;
}> = []
public _watchBy(context: any, callback: WatcherCallback) {
this._watchers.push({ context, callback } as any)
}
public _stopWatchBy(context: any) {
this._watchers = this._watchers.filter((w) => w.context !== context)
}
protected _emitValueChange(modificationTree: ModificationTree) {
for (const { callback } of this._watchers) {
callback(modificationTree)
}
}
protected _registerChild(field: () => string | string, child: Observable) {
const id = child._observableId
if (!child._watchedTargets[id]) {
child._watchedTargets[id] = {
target: child,
watcherCount: 0
}
}
child._watchedTargets[id].watcherCount++
child._watchBy(this, (modificationTree) => {
let s: string
if (typeof field === 'function') {
s = field()
} else {
s = field
}
this._emitValueChange({ [s]: modificationTree })
})
}
protected _unregisterChild(childOrChildId: Observable | string) {
let id: string
if (childOrChildId instanceof Observable) {
id = childOrChildId._observableId + ''
} else {
id = childOrChildId
}
const watchInfo = this._watchedTargets[id]
if (watchInfo.watcherCount > 1) {
watchInfo.watcherCount--
} else {
this._watchedTargets[id].target._stopWatchBy(this)
delete this._watchedTargets[id]
}
}
}