Post banner

01 February 2018 by Mike Vezzani

Horatio, Netflix, and Life before Computed Properties

So far I’ve really enjoyed my time with Vue.js. Great documentation, great developer productivity. It’s just enjoyable to work with.

While Vue.js has many things to enjoy, one great tool Vue.js gives is that of Computed Properties. Imagine the following scenario. Let’s say we’ve got a model of our data which we’ll call Horatio for now. The properties on this model may include

{
	birthdate: "Mon Mar 21 1990 04:33:29 GMT-0500 (EST)",
	name: Horatio McGuggenschlaufer,
	age: 27,
	amountOfFoodAvailableInCalories: 37453,
	daysOfFoodOnHand: 18.73,
	amountOfWaterAvailableInLiters: 15.25,
	daysOfWaterOnHand: 3.91,
	bingeWatchesNetflix: true
}

This data tells us a few things. First, Horatio has about 19 days worth of food and about 4 days worth of water on hand. He also likes to binge watch Netflix. Assuming he has some kind of bathroom solution in place such that he is able to continue watching Netflix without being interrupted, it would appear our dear Horatio McGuggenschlaufer can binge watch almost 4 days before his water supply is depleted, at which point he would be forced to break away from the screen and replenish his reserves. But what if we want to check in on him occasionally during his binge session to see how his food and water supplies are holding up as he burns season 5 of The Wire into his retinas? We could simply look at his daysWorthOfFoodOnHand and daysWorthOfWaterOnHand attributes. But what if Guggenschlaufer eats or drinks some during that time? First, some functions need to be implemented to subtract amounts from amountOfFoodAvailableInCalories and amountOfWaterAvailableInLiters.

var app = new Vue ({
  el: ‘#app,
  data: {
    ...
    amountOfFoodAvailableInCalories: 37453,
    daysOfFoodOnHand: 18.73,
    amountOfWaterAvailableInLiters: 15.25,
    daysOfWaterOnHand: 3.91,
    ...
  },
  methods: {
    eatMeal: function() {
      If (this.amountOfFoodAvailableInCalories > 667) {
        this.amountOfFoodAvailableInCalories -= 667;
      } else {
        this.amountOfFoodAvailableInCalories -= this.amountOfFoodAvailableInCalories;
      }
    },
    drinkWater: function() {
      If (this.amountOfWaterAvailableInLiters > 0.5) {
        this.amountOfWaterAvailableInLiters -= 0.5;
      } else {
        this.amountOfWaterAvailableInLiters -= this.amountOfWaterAvailableInLiters;
      }
    }
  }
})

Great! Functions are now in place to update food and water reserves. Anytime Horatio eats food (667 calories/meal) or drinks water (0.5 liters per drink), we update the amountOfFoodAvailableInCalories and amountOfWaterAvailableInLiters variables. But if we want to display how man days of food or water Horatio has left, we now need to create functions to update those properties in our data object and call them any time we call the eatMeal() / drinkWater() functions.

...
el: '#app',
data: {
  ...
	amountOfFoodAvailableInCalories: 37453,
	daysOfFoodOnHand: 18.73,
	amountOfWaterAvailableInLiters: 15.25,
	daysOfWaterOnHand: 3.91,
  ...
},
methods: {
  eatMeal() {
    ...
    this.updateFood();
  },
  drinkWater() {
    ...
    this.updateWater();
  }
  updateFood() {
    this.daysOfFoodOnHand = amountOfFoodAvailableInCalories / 2000; // Recommended calories in a day
  },
  updateWater() {
    this.daysOfWaterOnHand = amountOfWaterAvailableInLiters / 3.9 // Recommended liters of water per day
  }
}

We now have a workable solution in place. Whenever Horatio eats or drinks, the daysOfFood/WaterOnHand properties are updated, resulting in up to date information within our templates. Awesome!

Computed Properties; Simplifying Code and Taking Names

However, Vue.js gives us a Better Way™. What if, instead of having properties that contain the days of food and days of water amounts, we use a computed property? What is a computed property? Well I’m glad you asked! A computed property can be defined as a function that returns a value which is calculated from the values of an object’s properties. What is more, the calculated value is cached so future calls don’t execute the calculation code, thus saving resources. However, if any of the properties used in that calculation are changed, the next time the function is called the cache is invalidated, the calculation code is run, and the new value is cached and returned.

A simple example of this would be someone’s age. If you have stored someone’s birthdate in your database and exposed that value as a property on one of your Vue.js objects, you could add a computed property called age on that object that would calculate a person’s age based on their birthdate. Let’s see how this would play out for our dear Horatio.

...
el: '#app',
data: {
  ...
	amountOfFoodAvailableInCalories: 37453,
	amountOfWaterAvailableInLiters: 15.25,
  ...
},
methods: {
  eatMeal() {
    ...
  },
  drinkWater() {
    ...
  }
},
computed: {
  daysOfFoodOnHand() {
    amountOfFoodAvailableInCalories / 2000; // Recommended calories in a day
  },
  daysOfWaterOnHand() {
    amountOfWaterAvailableInLiters / 3.9 // Recommended liters of water per day
  }
}

So this is pretty neat, I think. Here, the daysOfFood/WaterOnHand properties were removed from the data object and placed inside the computed object. The result is a template that can be equally expressive, allowing you to pass in daysOfFood/WaterOnHand without having to define those properties on your object and constantly update them with custom function calls when certain properties change. And bonus! Values get cached until dependent properties change, making your code more performant!

Summary 5 hrs in

Vue.js continues to impress me. I enjoy the simplicity of it, the documentation is simple and understandable, and I feel as though I am able to better understand the code I’m writing. Up next in the 10 Hours With: Vue.js series; Components, Single File Components, and Creating a Modular Vue.js Application.


Author image
Mike · Software Developer

Mike graduated from Brigham Young University with a BA in Interdisciplinary Humanities. He was introduced to the Ruby programming language 5 years ago. Since then, he has pursued solving problems in JavaScript, C#, and Elixir. When not programming, he enjoys cooking, carpentry, and playing piano. He hates his computer mouse.