Limited set of reactive props for a data nested object
See original GitHub issueWhat problem does this feature solve?
Referencing a big object in the data of a component can lead to performance issues: indeed Vue automatically recursively observes all properties found in the object.
This is not ideal to reference big objects that are not just pure data or states, but especially in the context of a progressive migration of a legacy application to Vue (ie. adding new components on top of an existing architecture), one can have parts of existing big objects to observe for components to react seamlessly.
I had performance issues when referencing an object having itself references to Three JS stuffs (meshes…): interacting with the 3D scene was much slower after the instantiation of the Vue component, whereas I just needed some properties at the root of this object to become reactive.
Thus I suggest adding the possibility to specify a limited set of properties to observe for an object referenced in the data of a component.
A good practice in such case is certainly to isolate the needed properties inside a much smaller object without uncontrolled content, but in the context of a progressive migration, refactoring things cannot always be an option. Copying and/or partially freezing the object is not an option in my case as it needs to stay mutable for the existing application to keep working. In my case the interesting properties being of simple types (String, Number, boolean…) and being at the root of the big object, the entry point is the big object itself.
In my mind Vue is recommended for eg. over React for projects where you want a progressive migration towards a modern component-based framework, and in this context adding this feature would help.
(Previously discussed here: https://forum.vuejs.org/t/limited-set-of-reactive-props-for-a-data-nested-object/)
I could work on a PR, even if I don’t have a lot of time, but for the moment this is just a feature suggestion 😃
What does the proposed API look like?
// src/someLegacyModule.js
export const bigOject = {
propA: ...,
propB: ...,
bar: {
deeperProp: ...,
// lots of stuffs we don't need in our Vue components
}
// lots of stuffs we don't need in our Vue components
}
Initially I thought of something like the following, but it could be considered as not totally consistent with the framework as an import is needed:
import bigObject from '@/src/someLegacyModule'
import { PartialObserver } from 'vue'
export default {
template: `
<div>
{{ foo.propA }}
<div v-if="foo.propB">{{ foo.bar.deeperProp }}</div>
</div>
`,
data () {
return {
// only make needed properties reactive on bigOject (as it could be huge and very deep)
foo: PartialObserver(bigObject, ['propA', 'propB', 'bar.deeperProp']),
}
}
}
Or maybe something like this, without additional import:
export default {
data () {
return {
foo: {
// only make needed properties reactive on bigOject (as it could be huge and very deep)
__partialObserver: [bigObject, ['propA', 'propB', 'bar.deeperProp']])
}
}
}
}
The name of the added special property where we can define the limited list of properties to make reactive could be different: '_observeOnly'
, '_watchOnly'
, '_reactiveProps'
… ? Maybe adding a $
or _vue
prefix (but I know this is more for Vue internals) ?
It could also be separate, as not adding an extra level of indirection may be easier to implement:
export default {
data () {
return {
foo: bigObject,
__settings: {
foo: {
watchOnly: ['propA', 'propB', 'bar.deeperProp']
}
}
}
},
// ... or instead of the above:
// dataConfig: {
// foo: {
// watchOnly: ['propA', 'propB', 'bar.deeperProp']
// }
// },
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (2 by maintainers)
Top GitHub Comments
Thanks for the proposal. To make things non reactive you can use
Object.defineProperty
orObject.freeze
if you don’t want to modify the object anymore which is also a simple straight call toHere is an example using Object.defineProperty and Object.freeze: https://jsfiddle.net/posva/fdruqp3v/
This will allow you to create your PartialObserver function or even a plugin to handle a nonReactive property. There is also https://github.com/rpkilby/vue-nonreactive which uses a slightly different solution
#2637