Vue Computed Properties

Vue templates are meant to be simple and easy to read, but complex logic can make them messy to read. This is where computed properties come in. Computed properties are functions that act like properties in Vue.

Basic Example

For example, let's say we wanted to reverse a string. We could do something like this:

const app = Vue.createApp({})
const vm = app.mount('#app')
<div id="app">
  {{ message.split('').reverse().join('') }}
</div>

While this does work, it can make our template look bloated and difficult to read. But with computed properties, it is possible to make the template much cleaner.

const app = Vue.createApp({
  data: function () {
    return {
      message: 'Hello'
    }
  },
  computed: {
    reversedMessage: function () {
      return this.message.split('').reverse().join('')
    }
  }
})

const vm = app.mount('#app')
<div id="app">
  <p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>

Computed Properties vs. Methods

While methods could produce the same result as computed properties, a computed property has the advantage of caching its value, so that function will only be invoked when the data has changed. This caching can significantly improve the application's performance.

The example below contains a method and a computed property. Both return the current date and time when the function was invoked. When the Vue instance is mounted, both the method and the computed property will output the same result. But if the Vue instance is updated, causing the instance to re-render, you will see that while the method's time will update, the cached computed property will not.

const app = Vue.createApp({
  methods: {
    now: function () {
      const date = new Date();
      return date.toLocaleString()
    },
    update: function () {
      this.$forceUpdate();
    }
  },
  computed: {
    then: function () {
      const date = new Date();
      return date.toLocaleString()
    }
  }
})

const vm = app.mount('#app')
<div id="app">
  <p><strong>Method:</strong> {{ now() }}</p>
  <p><strong>Computed Property:</strong> {{ then }}</p>
  <button @click="update">Update</button>
</div>

Filtered Data

One of the key uses of computed properties is creating filtered versions of data properties. This can be a convenient way of creating groups or categories.

In the example below, the movies array contains movie objects. The computed properties allow for the movies to be divided into different genres.

const movies = [...]

const app = Vue.createApp({
  data: function () {
    return { movies: movies }
  },
  computed: {
    action: function () {
      return this.movies.filter(movie => movie.genre.includes('Action'))
    },
    comedy: function () {
      return this.movies.filter(movie => movie.genre.includes('Comedy'))
    },
    romance: function () {
      return this.movies.filter(movie => movie.genre.includes('Romance'))
    }
  }
})

const vm = app.mount('#app')
<div id="app">
  <h4>Action</h4>
  <ul>
    <li v-for="movie in action">{{ movie.title }}</li>
  </ul>
  
  <h4>Comedy</h4>
  <ul>
    <li v-for="movie in comedy">{{ movie.title }}</li>
  </ul>
  
  <h4>Romance</h4>
  <ul>
    <li v-for="movie in romance">{{ movie.title }}</li>
  </ul>
</div>