30 Days of Vue - Methods and Computed Properties

30 Days of Vue - Methods and Computed Properties

Methods in a Vue instance behave like normal JavaScript functions and are evaluated only when explicitly called. Instead of using methods we could always write our intended functionality change _inline_ in the template.

Methods in a Vue instance behave like normal JavaScript functions and are evaluated only when explicitly called. Instead of using methods we could always write our intended functionality change inline in the template.

Let’s see an example of this. We’ll reuse an example seen in the Vue documentation that involves reversing a series of characters from a string. We’ll first create a Vue instance that contains a single message property that has a value of 'Greetings!':

new Vue({
  el: '#app',
  data: {
    message: 'Greetings!',
  },
});

In the template, we’ll look to bind the message directly and also bind the message in its reversed state. We’ll reverse the value of message by splitting the property into an array of characters (.split('')), reversing the elements in the array (.reverse()), and rejoining the reversed array back into a single string (.join('')).

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
    <link rel="stylesheet"
      href="https://unpkg.com/bulma/css/bulma.css" />
  </head>
  <body>
    <div id="app">
      <div class="card">
        <header class="card-header card-header-title">
          <span>Original:</span>
          {{ message }}
        </header>
        <header class="card-header card-header-title">
          <span>Reversed:</span>
          {{ message.split('').reverse().join('') }}
        </header>
      </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

With the help of the styling given to us by Bulma, our simple app will look like the following:

This is image title

There’s nothing inherently wrong with specifying functionality change, like the above, inline. However, methods are often times more appropriate to use when the intended changes get harder to decipher.

We can change the above example to instead use a method in our Vue instance to help reverse the message string:

new Vue({
  el: '#app',
  data: {
    message: 'Greetings!',
  },
  methods: {
    reverseString(string) {
      return string.split('').reverse().join('');
    },
  }
});

The method is given a name of reverseString and expects a payload. We can declare this method in the template and pass in the message property as the payload:

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
    <link rel="stylesheet"
      href="https://unpkg.com/bulma/css/bulma.css" />
  </head>
  <body>
    <div id="app">
      <div class="card">
        <header class="card-header card-header-title">
          <span>Original:</span>
          {{ message }}
        </header>
        <header class="card-header card-header-title">
          <span>Reversed:</span>
          {{ reverseString(message) }}
        </header>
      </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

Our UI would behave just the way it had before by displaying the message greeting and the reversed version right below it:

This is image title

Functionality wise — the above two examples achieve the same thing. Methods might be seen to be more appropriate since it keeps the template cleaner and easier to understand.

We’re also able to achieve the same outcome as above with the use of another property — called the computed property.

Computed Properties

Computed properties are used to handle complex calculations of information that need to be displayed in the view. For our third iteration in building the same simple app, we’ll introduce a computed property called reverseMessage that simply reverses the message data property as we’ve done before:

new Vue({
  el: '#app',
  data: {
    message: 'Greetings!',
  },
  computed: {
    reverseMessage() {
      return this.message.split('').reverse().join('');
    },
  }
});

In the template, we can render the value of the reverseMessage computed property just as we would have rendered any other data property:

<html>
  <head>
    <link rel="stylesheet" href="./styles.css" />
    <link rel="stylesheet"
      href="https://unpkg.com/bulma/css/bulma.css" />
  </head>
  <body>
    <div id="app">
      <div class="card">
        <header class="card-header card-header-title">
          <span>Original:</span>
          {{ message }}
        </header>
        <header class="card-header card-header-title">
          <span>Reversed:</span>
          {{ reverseMessage }}
        </header>
      </div>
    </div>
    <script src="https://unpkg.com/vue"></script>
    <script src="./main.js"></script>
  </body>
</html>

With this, our app will behave as desired:

This is image title This begs the question, what difference is there to using a computed property or having a method instead return a value?

Methods vs. Computed Properties

In the examples above, using a method or a computed property pretty much achieved the exact same outcome. The key difference in using computed properties is that computed properties are cached based on the dependencies they depend on.

If we take a look at the reverseMessage computed property we’ve declared, we can see it has one data dependency - the message property.

computed: {
  reverseMessage() {
    return this.message.split('').reverse().join('');
  },
}

The value of reverseMessage directly depends on the message data property. When the value of message changes, so does reverseMessage. Computed properties are useful because as long as the dependant data property (message) remains constant (i.e. unchanged), calling the computed property (reverseMessage) multiple times will always return the same cached value.

Let’s see a simple example of this visually. We can place a console.log()message in the computed property function to alert us when the function has been run:

computed: {
  reverseMessage() {
    console.log('computed function is run!');
    return this.message.split('').reverse().join('');
  },
}

In the template, we can aim to render the reverseMessage computed property a couple of times:

<div id="app">
  <div class="card">
    <header class="card-header card-header-title">
      <span>Original:</span>
      {{ message }}
    </header>
  </div>

  <div class="card">
    <header class="card-header card-header-title">
      <span>Reversed:</span>
      {{ reverseMessage }}
    </header>
  </div>

  <div class="card">
    <header class="card-header card-header-title">
      <span>Reversed:</span>
      {{ reverseMessage }}
    </header>
  </div>

  <div class="card">
    <header class="card-header card-header-title">
      <span>Reversed:</span>
      {{ reverseMessage }}
    </header>
  </div>
</div>

By running the application and opening our browser console, we’ll see the console.log() message logged only once:

This is image title

The first time the reverseMessage property is computed, its value is cached. With every other call to render the value of reverseMessage, the messageproperty hasn’t changed, so the cached result is simply returned without running the computed function again.

If we repeat a similar example but instead call methods multiple times in the template, the console.log() message will be run every single time the method is declared:

This is image title

In conclusion, though methods can be used in place of computed properties; computed properties should essentially be used if we intend to compute a value from a data property. Caching can help our application with performance once our application starts to have countless properties with each derived functionality potentially being somewhat computationally expensive.

Here’s a table that highlights the main differences between using methods or computed properties:

This is image title

A good rule of thumb to follow:

  • Use methods when responding to changes (e.g. clicking a button, submitting a form, etc.) or to run explicit functionality change within the instance (e.g. have a method be called from a lifecycle hook).
  • Use computed properties for data manipulation (e.g. create a sorted array from an unsorted array in the instance).

If you have any questions whatsoever, feel free to leave a comment and I’ll answer as best as I can. I’m always available on Twitter as well - @djirdehh!

You can find all the code samples of today in the Github Repo - fullstackio/30-days-of-vue.

If you’re brand new to Vue.js and are interested in diving into other topics -feel free to check out https://www.fullstack.io/30-days-of-vue/.

vue vuejs javascript

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Vue Native is a framework to build cross platform native mobile apps using JavaScript

Vue Native is a framework to build cross platform native mobile apps using JavaScript. It is a wrapper around the APIs of React Native. So, with Vue Native, you can do everything that you can do with React Native. With Vue Native, you get

Creating a Custom Tooltip Component in Vue

There are plenty of libraries out there that will have you up and running with a good tooltip solution in minutes. However, if you are like me, you are sick and tired of giant dependency trees that have the distinct possibility of breaking at any time.

Vue ShortKey plugin for Vue.js

Vue-ShortKey - The ultimate shortcut plugin to improve the UX .Vue-ShortKey - plugin for VueJS 2.x accepts shortcuts globaly and in a single listener.

A Vue component to hzqing vue Timeline

hzqing-vue-timeline . Vue's timeline plugin .A Vue component to hzqing-vue-timeline A Vue time plugin

Vue.js image clipping Components using Vue-Rx

vuejs-clipper .Vue.js image clipping components using Vue-Rx. Add image clipping components to your Vue application in nothing flat. Touch devices supported and fully responsive.