Where do I put my variables within a component, and why there? I don’t know about you, but to me, it wasn’t obvious in the beginning, what kind of information should I store under the ominous data()
method, and what goes under computed.
Data()
There is a general saying that in Vue, everything is reactive – by that, they usually mean that every variable is observed, and watched for changes, which isn’t the whole truth. Reactivity is added upon the creation of the component – I will talk about lifecycle hooks more in-depth later –, so every variable that was added before that is going to be observed automatically. The data()
method is the perfect example of that, whatever variable you may return in that is going to be reactive.
The computed methods, as the name suggests, are great for values that aren’t directly derived from the data variables, but you still use them fairly often, while wanting to leave the source untouched. As an example, let’s say you have an array of hashes in the data, music albums with basic information, and the applicable genres and the track list also included as arrays:
data() {
return {
albums: [
{ id: 569, artist: ‘Scandroid’, title: ‘Scandroid’, tags: [...], year: ‘2016’, tracks: [...] },
{ id: 732, artist: ‘The Midnight’, title: ‘Endless Summer’, tags: [...], year: ‘2016’, tracks: [...] }
{ id: 1006, artist: ‘Confrontational’, title: ‘The Burning Dawn’, tags: [...], year: ‘2017’, tracks: [...] }
{ id: 1161, artist: ‘The Anix’, title: ‘Shadow_movement’, tags: [...], year: ‘2018’, tracks: [...] }
]
}
}
Computed
Let’s say this is your user’s personal music collection, but you also want him to be able to view his collection by tags, and show the number of albums he has for each tag, such as: ‘80s (1), electronic (4), retrowave (2), synth pop (1)’ etc. This information can be derived from the albums array, but you need to modify the information to fit the purpose. There is no need to send another request to the backend to obtain this information, so you can just create a new computed method to return all the data you need for your tags:
computed: {
uniqueTagsWithCount() {
const uniqueTags = []
return this.albums
.map(album => album.tags)
.flat()
.forEach((tag) => {
if (!uniqueTags .find(ut => ut.name === tag.name)) uniqueTags.push({ id: tag.id, name: tag.name, count: 1 })
else uniqueTags .find(ut => ut.name === tag.name).count++
})
return uniqueTags
}
}
Assuming the tags on each album are represented as an array of hashes, you can map and flatten them into one array, then iterate through the result to remove the duplicates, and add a counter. The returned array will be suitable for displaying any tags in the template, without having the modify the original data array.
What’s also great about computed methods, is that they stay the way they are, until their source, on which their calculations are based, is changed. This means, that each time you decide to re-get the album list from your server, the unique tags method will be recalculated.
Side note: this example is for explanation purposes only, from the point of optimization, if you store a large number of similar records in your database, it’s probably a better idea to cache the unique tags with their respectable counter, and leave the calculation to the server instead of the client.
$options
We’ve talked about the relation between the data()
method and the computed variables, so what’s $options
good for?
It’s an often overlooked part of a Vue component, and some may never even use it. But in certain cases, we might not want everything to always be reactive. Or sometimes you just come to the conclusion that you want to return static custom properties that don’t need to be calculated, but you also know that the client is not supposed to change that information. What would be the point of putting it into the data()
, thus making it reactive then? It would be an overhead, something unnecessary that bloats your fast and streamlined application.
new Vue({
customOption: 'foo',
created: function () {
console.log(this.$options.customOption) // -> 'foo'
}
})
To sum it up: you generally want to store information in the data()
method if it’s something you receive from your backend through a request. The computed
methods will allow you to quickly access and modify parts of this data: to map it, filter it, or otherwise use them in custom calculations. The $options
represents a non-reactive custom property that you can access within the component.