Vue.js Computed Properties in Depth

Last updated on August 14, 2022. Created on March 28, 2022.


As we learned in the previous post, VueJs computed properties help us declutter complex template expressions and help make our code readable and maintainable. That’s the gist of it, we are going to have an in-depth look into them inside this post.

To help us along, let’s create a new Vue app.

Try this!
<div id="app">
  <p> {{ personalInfo }} </p>
</div>

<script src="https://unpkg.com/[email protected]"></script>
<script>
  let app = Vue.createApp({
    data: function () {
      return {
        firstName: 'Vue',
        lastName: 'Noob',
        age: 21,
        locality: 'Vueland',
      };
    },
    computed: {
      personalInfo(){
        return `My name is ${this.firstName} ${this.lastName}, I am ${this.age} years old. I am based in ${this.locality}.`;
      }
    }
  }).mount('#app');
</script>

Reactivity in Computed Properties

Computed properties do observe changes in all of their dependencies and update accordingly. In the above instance, the personalInfo computed property observes the changes in the firstName, lastName, age and locality variables, when it detects changes in any of thier values it updates itself to reflect the changes.

Try changing the values of those variables to see the results.

Caching in Computed Properties

One essential feature that computed properties have is caching, this is an advantage that computed properties have over methods, a Vue property that will be covered later.

Caching in Vue’s computed properties can be explained like this, when a computed property has been resolved, the resulting value is cached by Vue, hence when new references are made to it, the cached value is returned instead of Vue re-running the expression that resolved to our computed property which is what happens in the case of methods.

Computed properties will only re-evaluate when one of their dependencies have changed. This is an important characteristic as it helps save on physical resources, especially when running complex expressions that require a lot of computations. This is more so when apps grow and the codebase becomes bigger.

Computed Properties Shortzola sercomings

While computed properties caching is sound it does fall short in some cases, copy and run the following modification to our above example.

Try this!
<div id="app">
<p> {{ personalInfo }} </p>
+ <p> {{ morePersonalInfo }} </p>
+ <p> {{ morePersonalInfoDelayed }} </p>
</div>

<script src="https://unpkg.com/[email protected]"></script>
<script>
let app = Vue.createApp({
   data: function () {
     return {
       firstName: 'vue',
       lastName: 'noob',
       age: 21,
       locality: 'Vueland',
+       time: Date.now(),
+       morePersonalInfoDelayed: ''
     };
   },
   computed: {
     personalInfo(){
       return `My name is ${this.firstName} ${this.lastName}, I am ${this.age} years old. I am based in ${this.locality}.`;
     },
+     morePersonalInfo(){
+       return `I'll be travelling on ${new Date(this.time).toUTCString()}.`;
+     }
   },
+   mounted(){
+     setTimeout(() => {
+       this.morePersonalInfoDelayed = this.morePersonalInfo;
+     }, 5000);
+   }
}).mount('#app');
</script>

The mounted() function in the above example is a lifecycle hook, a topic that will be covered later.

In our example, you’ll notice that both computed properties morePersonalInfo and morePersonalInfoDelayed give us the same string despite morePersonalInfoDelayed being resolved 5 seconds later. This is where computed properties fall short, when dealing with non-reactive dependencies such as Date.now() and Math.random(). In such cases using methods is the proper way to go about it.

Customizing Computed Properties

Computed properties are by characteristic getter-only, i.e. we only expect to get values from them and should not be assigning values to them. Mutating or assigning values to computed properties is futile since the value obtained from them is a temporary snapshot of the state and is subject to change when its dependencies change a feature we target to make use of when using them in the first place. Also trying to do this will trigger a runtime warning.

In the few cases where the need to manually customize computed properties behavior, we can do so by providing getters and setters.

Observe the following example.

Try this!
<div id="app2">
<p> {{ priceOfAnItem }} </p>
</div>

<script src="https://unpkg.com/[email protected]"></script>
<script>
let app2 = Vue.createApp({
   data: function () {
     return {
       item: 'Apple',
       price: '2'
     };
   },
   computed: {
     priceOfAnItem: {
       get(){
         return `One ${this.item} costs ${this.price} dollars`;
       },
       set(resolvedVal){
         [,this.item,,this.price,] = resolvedVal.split(' ');
       }
     }
   },
   mounted(){
     setTimeout(() => {
       this.priceOfAnItem = `One Orange costs 5 dollars`;
     }, 3000);
   }
}).mount('#app2');
</script>

If you run the above example you’ll see that after 3 seconds the item and price values change to "Orange" and 5 respectively, that happens after we update the value of the computed property with help from the setter.

Updating the computed property this way frees us from experiencing a runtime warning and unexpected results in our app.

It is advised to use getter functions to only perform pure computations and avoid handling side effects creating activities such as making function and DOM altering calls, such side effects making logic can be performed inside Vue’s watchers.

All of the source code to the examples above is found inside this file.

Next

VueJs Directives: Data Binding in VueJs

Previous

VueJs Variables: Data and Computed Properties in VueJs

Subscribe to the VueNoob Newsletter

[[[ noty.message ]]]

By using this site, you agree that you have read and understand its Privacy Policy.