VUE

Understanding computed properties in VueJS

In this post we’ll see what are computed properties, how to write a computed property and let’s understand how a computed property is designed behind the scenes.

Don’t forget to visit the links in the references section.

What are the computed properties?

Computed properties are like normal methods in Vue, but with the caching ability on the reactive dependencies.

An example of computed property

We have a grocery list of items and we’d like to display the total price of the items. So, when changing the price of an item, the total gets updated too.

Here’s the grocery list component.

<template>
 <div>
  <table>
   <thead>
    <tr>
     <th>Name</th>
     <th>Price</th>
     <th>Quantity</th>
    </tr>
    <tr></tr>
    <tr></tr>
   </thead>
   <tbody>
    <tr v-for=’item in groceries’ v-bind:key=’item.id’>
     <td>{{item.itemName}}</td>
     <td><input type=’number’ v-model=’item.price’ min=’0’ /></td>
     <td><input type="number" v-model=’item.quantity’ min=’1’/></td>
    </tr>
    <tr>
     <td>
     Total Price:
     </td>
     <td><b>${{ groceriesCount }}</b></td>
     <td></td>
    </tr>
   </tbody>
  </table>
 </div>
</template>
<script>
export default {
 name: ‘GroceriesList’,
 data () {
  return {
   groceries: [
    { itemName: ‘Rice’, price: 20, quantity: 1 },
    { itemName: ‘Flour’, price: 80, quantity: 1 },
    { itemName: ‘Oats’, price: 40, quantity: 1 }
   ]
  }
 },
 computed: {
  groceriesCount: function () {
   return this.groceries.reduce(
    (acc, val) => acc + parseInt(val.price),
    0
   )
  }
 }
}
</script>

For our convenience, I’ve textboxes for displaying price of the items so we can directly edit and see the computed property in action.

Notice the grocieriesCount computed property, we haven’t included the quantity of the items yet. But, now try to change the quantity of the items and observe the total price. The total price will only change when changing the price of any item. So, the price is a “reactive dependency” for the computed property.

Test for computed property caching

In the above example, we’ve just used the total price of the groceries only once.

Let’s use the computed property in a h2 tag and try to change the price of any item.

  <h2>Total price: ${{groceriesCount}}</h2>

After adding the above h2 tag in the template section, run the app.

Open developer tools and place a breakpoint in our computed property (groceriesCount). Now, try to change the price of any grocery item and your breakpoint should hit only once.

Though we have used the computed property (groceriesCount) twice in the template our breakpoint got hit only once. This is the caching ability of the computed properties.

Computed setters

By default computed properties are getters but we can have setters.

computed: {
 fullName: {
  get: function() {
   return this.firstName + this.lastName;
  },
  set: function(value) {
   let names = value.split(‘ ‘);
   this.firstName = names[0];
   this.lastName = names[names.length - 1];
  }
 }
}

If we set the fullName in a method, the firstName and lastName props will correctly.

How do computed properties work under the hood?

Vue has a dependency tracking system, which tracks the reactive dependencies.

The data in a component converts into getters and setters. So, it is not specific to the computed properties. Vue creates the getters and setters for every property in the data() function.

Here’s how reactivity works: When accessing a value via getter, it will add to the dependencies and when changing a value via a setter, the setter will notify who depends on the property and re-renders the DOM.

Here’s the sample code to understand how the reactivity works for a property.

function defineReactive (obj, key, val) {

  const dep = new Dep();

  Object.defineProperty (obj, key, {
    get: function () {
      // check if it’s not already a dependancy
      if (dep.target)
        buildDependants(val); // This will push the dependencies to some array to use it later      

      return val;
    },
    set: function (newVal) {
      const value = currentValue; //current value of prop
      // some basic validations to perform
      validations();

      // set the newVal 
      value = newVal;

      // notify the depedencies
      // This will notify all depending props
      dep.notify(); 
    }
  })
}

The Dep() function is a dependancy tracker in Vue.

As you can see, we capture the dependencies in the get function and we’ll notify all the depending properties when changing the value in set function via dep.notify().

Here’s the source code that converts properties to getters and setters.

References

Disqus Comments Loading...
Share
Published by
Karthik Chintala

Recent Posts

2 Good Tools To Test gRPC Server Applications

In this post, we’ll see how to test gRPC Server applications using different clients. And… Read More

12 months ago

Exploring gRPC project in ASP.NET Core

In this post, we'll create a new gRPC project in ASP.NET Core and see what's… Read More

1 year ago

Run dotnet core projects without opening visual studio

In this blog post, we’ll see how to run dotnet core projects without opening visual… Read More

1 year ago

Programmatically evaluating policies in ASP.NET Core

Programmatically evaluating policies is useful when we want to provide access or hide some data… Read More

1 year ago

Multiple authorization handlers for the same requirement in ASP.NET Core

We saw how we could set up policy-based authorization in our previous article. In this… Read More

1 year ago

Policy-Based Authorization in ASP.NET Core

What is policy-based authorization and how to set up policy-based authorization with handlers and policies… Read More

1 year ago

This website uses cookies.