Open littledan opened 2 years ago
I'll put together some concrete examples. I've seen this come up in MVVM (model-view-viewmodel), where the majority use case of an @observe
may be field-like definitions, but there are also cases where you need to evaluate logic during the get
or set
to provide reactivity, such as:
class MyViewModel {
// non-reactive:
// @observe
// accessor format = "simple";
// reactive:
#format;
// I still want to observe changes to `format`
@observe
accessor format {
// getter that uses lazy init
get() { return this.#format ??= getDefaultFormat(); }
// setter that updates other observed values
set(value) {
if (this.#format !== value) {
const oldFormat = this.#format;
this.#format = value;
this.text = this.reformat(this.text, this.#format, oldFormat);
}
}
}
// I want to observe changes to `text`
@observe
accessor text = "";
}
The workarounds for this both would be a poor developer experience:
// using `accessor`
class MyViewModel {
// NOTE: decorator application order is *very* important here.
@observe
@onSet(function(oldFormat, newFormat) {
if (oldFormat !== newFormat) {
this.text = this.reformat(this.text, oldFormat, newFormat);
}
})
@lazyInit(() => getDefaultFormat());
accessor format;
...
}
// entangling getter/setter
const observeFormat = createAccesorPairDecorator(observe); // and having to do this for 10+ properties...
class MyViewModel {
#format;
@observeFormat.getter
get format() { ... }
@observeFormat.setter
set format(value) { ... }
...
}
Thanks for these interesting examples. I agree that it looks cleaner with this feature.
A big new capability that this feature enables is allowing decorators to work across a getter/setter pair. The README here mentions observer decorators. Do you have any more concrete examples of when observing or otherwise decorating a getter/setter pair is useful? The observer decorators I've seen so far would make more sense in conjunction with a simple
accessor x;
, so I'm just missing context on the use cases here.