Hands-on Vue.js for Beginners (Part 6)
Tags: vue, javascript, beginners, tutorial
Published: 2019-03-01 14:23:46

Let's talk about computed properties.

So far you've learned how **Vue** handles its own local state, the one we put inside `data`, and how a component can handle its `prop` properties - the ones that get handed down by the parent.

However, there is a type of properties in **Vue** which are called **Computed Properties**. Let's take a look at these today.

We're going to use a clean slate today, so that we can build a clear example. Here's the code.

```html
<html>

<head>
  <title>Vue 101</title>
</head>

<body>
  <div id="app">
    <age-calculator></age-calculator>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>
    Vue.component('age-calculator', {
      template: `
        <p>
          NAME has been kicking butt for X days!
        </p>
      `
    });

    const app = new Vue({
      el: '#app'
    });
  </script>
</body>

</html>
```

I've gone ahead and added the scaffolding for an `age-calculator` component, right now it only outputs a `<p>` tag with an X where we're going to perform some sort of calculation. I've also added the corresponding tags `<age-calculator>` to the `div#app`. 

If you need a refresher on basic components, take a look at [Part V](https://dev.to/vuevixens/hands-on-vuejs-for-beginners-part-5--1jbi) of this series, or better yet, nosedive [the official docs](https://vuejs.org/v2/guide/components.html)!

# When a simple prop isn't enough

Before we write any code, let's talk about what we're trying to accomplish.

I want to have a component where I pass it someone's age, and it will tell us how many days they've been around to enjoy avocados. If you don't like avocados then this is where our relationship ends, have a nice life.

Let's tackle the easy tasks that we already know how to accomplish, first we need an array of people with ages so that we can loop through it and output a bunch of components. Let's add the corresponding `data`.

```js 
const app = new Vue({
  el: '#app',
  data: {
    people: [
      { name: 'Mario', age: 38 },
      { name: 'Luigi', age: 38 },
      { name: 'Samus', age: 31 },
      { name: 'Link', age: 20 },
      { name: 'Marina', age: 32 },
      //Add yourself here :)
    ]
  }
});
```

Now, let's set up our `v-loop` to output an `age-calculator` per each one.

```html
<div id="app">
  <age-calculator v-for="person in people" :key="person.name"></age-calculator>
</div>
```

Awesome, now let's allow the `age-calculator` component to receive a `person`, remember we do this with a `prop`. So first, let's add this new `prop` to the component.

```js
Vue.component('age-calculator', {
  props: {
    person: {
      type: Object,
      required: true
    }
  },
  template: `
    <p>
      {{ person.name }} has been kicking butt for X days!
    </p>
  `
});
```

**Bonus!** Before you learned that to declare the props that a component can receive, you set up an array of strings `props: ['person']` and this is fine in most cases. But what happens if we want a bit more control?

You can also, like in this case, set `props` to be equal to an **object**. Inside this object, we can create a property per each property we want to declare. 

Inside the property declaration, in this case `person`, we can set some configuration values. 

`type` to declare which (duh) **type** of data we're passing, so `Object`, `Array`, `String`, `Number` for example. 

`required` is a **boolean** that allows us to mark this property as required for the component to work. 

You can also set a `default` value, but we're not going to use that here.

Next, look at the template. We are now outputting the person's name `{{ person.name }}` onto the `<p>` tag. 

One more thing before we can actually run this in our browser though. Can you tell what we're missing?

We still need to pass the actual `person` to the `age-calculator` component!

Go into the render loop and pass in our variable.

```js
<age-calculator 
  v-for="person in people" 
  :person="person"
  :key="person.name"></age-calculator>
```

Go ahead and run this in your browser to check that everything is working. Baby-steps!

**Note** Before we move on, if you're curious what setting a `prop` to **required** will do for you, try removing this last bit we did when we pass the person to the component and look at your dev tools in the console section.

![](https://thepracticaldev.s3.amazonaws.com/i/0uhzn5szgsbdfscmm64j.png)

Handy, ain't it? 👌

# The actual Computed Property

Alright, enough setting up and review. 

We still have one more feature to tackle inside our component, we want to **calculate** the number of days each person has been alive. 

Granted, it's not a very hard calculation, we just have to multiply 365 times the number of years (we're not going to go hardcore with JS Dates here). And in fact, we could go ugly and direct and put this straight into our template.

```js
template: `
        <p>
          {{ person.name }} has been kicking butt for {{ person.age * 365 }} days!
        </p>
      `
```

This works, sort of. But what happens when you require more logic? A harder `computation`, some ifs/ands/ors/whens/beers? Then you're in a real problem because you can't really put that much logic inside the template, or it's going to get unmanageable real quick.

Here's where **computed properties** shine. Computed properties are in the end functions, that will execute a bit of code, and return a value. This value is now treated like a property, which means we can straight up use it in our template.

Let's take a look at how to set it up. First, let's add the computed wrapper to our component.

```js 
Vue.component('age-calculator', {
  props: {
    person: {
      type: Object,
      required: true
    }
  },
  template: `
    <p>
      {{ person.name }} has been kicking butt for {{ person.age * 365 }} days!
    </p>
  `,
  computed: {
    // Computed props go here
  }
});
```

So far so good, in fact this structure is the exact same one we have been using for `methods`, remember? (If you're thinking a method could also solve our problem, you're on the right track - we'll talk about this in a minute.)

Let's create a new **computed** property called `daysAlive`, it needs to be a function, and it needs to return something.

```js
computed: {
  daysAlive() { //Remember, computed props are functions in the end
    return this.person.age * 365
  }
}
```

Take note that just like in `methods` we need to access the `person` prop though `this`, only inside the template we can use it directly! Other than that, nothing too fancy going on.

Now let's use this new `daysAlive` prop in our template.

```js
template: `
  <p>
    {{ person.name }} has been kicking butt for {{ daysAlive }} days!
  </p>
`,
```

Note that we're outputting the value of the `daysAlive` --**property**--, (aha moment here). **Vue** treats computed props as, well, props - so we can use this here as you would a `props` prop, or a `data` prop. 

In fact, **Vue** makes it so that if you would need to use this prop inside a `method` for example, you would have to access it through `this.daysAlive`. Neat right? It ACTUALLY becomes a prop. 🤯

YAY, run it in the browser and bask in your awesomeness.

![](https://thepracticaldev.s3.amazonaws.com/i/0q9lul5pzyjq6p8z03sh.jpg)

# Methods vs Computed Properties

You may have noticed a lot of similarities between methods and computed props, I mean, they're basically identical at code level. However there is a CORE difference that you need to understand in order to harness them fully.

**Computed properties** get cached. 

What this means is, in the simplest possible way to explain it, that behind the scenes **Vue** will "read" your code and look for **reactive dependencies** - so `data` props and `props` props. It will **watch** these properties, and whenever they change, **Vue** will recalculate the value of your computed property. If they don't change, it'll just use a cached/stored value.

Methods, on the other hand, are ran EVERY time - there is no caching, no code reading, no magic. They're just plain old functions.

Why does this matter? When are these functions called?

Every time your component/app re-renders (so every time a component's data change, or every time it's parent's data changes), **Vue** will figure out if that data is tied to a **computed** property, if it's not - it won't call this function again. For regular methods however, they will be re-run every time!

For this example, where we're doing a very simple calculation for these few objects it doesn't really matter, frankly. But when you start doing some serious code weightlifting on top of a thousand components, then you're going to want to leverage this caching or your app is going to take a hit on each render cycle.

If you want to read more, here's a link to the official docs regarding [computed properties](https://vuejs.org/v2/guide/computed.html).

Here's the complete code for today.

```html
<html>

<head>
  <title>Vue 101</title>
</head>

<body>
  <div id="app">
    <age-calculator 
      v-for="person in people" 
      :person="person"
      :key="person.name"></age-calculator>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>
    Vue.component('age-calculator', {
      props: {
        person: {
          type: Object,
          required: true
        }
      },
      template: `
        <p>
          {{ person.name }} has been kicking butt for {{ daysAlive }} days!
        </p>
      `,
      computed: {
        daysAlive() {
          return this.person.age * 365
        }
      }
    });

    const app = new Vue({
      el: '#app',
      data: {
        people: [
          { name: 'Mario', age: 38 },
          { name: 'Luigi', age: 38 },
          { name: 'Samus', age: 31 },
          { name: 'Link', age: 20 }
        ]
      }
    });
  </script>
</body>

</html>
```

That's it for today! Thanks for reading, and we'll keep on going next week with `watchers`! 🕵️‍♀️ 👀