Vue - like recursive tracking?
lifeart opened this issue · 9 comments
case - extenally controlled state object.
like:
var state = {
name: 'Age',
items: [ { name: 'Pet' }, { name : 'Book' } , { name: { firstName: 'foo' } } ]
}
recursive tracking example - https://gist.github.com/lifeart/d6237e0129e603b23d1aa8e8d4b07504
like makeTracked(state);
also, it's possible to add one more object tracking option - track only defined properties (without proxy), patching native getters/setters.
Recursive tracking is very difficult/expensive, because it means that whenever you update a value you have to wrap it, or you have to rely heavily on native Proxy (which is itself pretty expensive). I do see the use case for deeply tracked objects, especially for rapid prototyping, but I want to make sure it won't have any impacts on shallow tracked objects/code.
I think maybe a @deepTracked
decorator, which specifically creates a deep/recursive wrapping Proxy setup (and thus only works with USE_PROXY=true
) could work nicely. I think it should also only wrap arrays and pojos - any kind of class should stop recursive wrapping (this is very important actually, for private fields). Maps/Sets could maybe continue it, we can think about it as we implement.
I do think it’d also be possible to construct an object based on the exist shape, using defineProperty like you suggest. It’s a bit trickier to think how that should work - do we track objects within arrays? Does that mean we add/remove getters/setters as objects are added to the array? Maybe we could add a @trackedShape
specifically for this
I think it should have same as "proxy" behavour, but, only on defined properties, and redefine array instance methods to "refill" new objects. Setting property must execure shapeTracker
on setted value to prevent possible tracking leakings like - this.items = Object.assign({}, this.items)
It should work like a "glue" and spread autotracking for any item having shape tracked parent or added as array item or property value.
Yeah, thinking about it more I think that makes sense. We should maybe actually change the default behavior of TrackedObject to add getters/setters for it’s initial props when proxies are disabled, but only shallow. Then the behavior would match for deepTracked
So I think the first step is actually to do that second part, enable TrackedObject
when proxies are disabled and manually install getters/setters for the properties passed to its constructor. I'll try to do it soon, if you have a chance though PRs are welcome 😄
should we patch original object or class properties? I think it make sense to support both cases
I think TrackedObject
should not alter the original object, to match the APIs of the other classes. Dynamically tracking values on a existing object may belong in a separate utility, could be useful, but it’s also definitely powerful, could have some consequences we should think through.
Closing this as a non goal, things have changed a bit, this library is no longer going to support IE11