In Vue.js, there are several ways to set static or dynamic values to display on the template. These include using text interpolation, directly hardcoding into your HTML, or even using simple expressions to modify the data.
This is where computed properties come in super handy. In this tutorial, we’ll go over the basics of using computed properties in Vue.js. We’ll then put all our newfound skills into practice by building a live example app.
Here’s what we’ll cover:
In Vue.js, computed properties enable you to create a property that can be used to modify, manipulate, and display data within your components in a readable and efficient manner.
You can use computed properties to calculate and display values based on a value or set of values in the data model. It can also have some custom logic that is cached based on its dependencies, meaning it doesn’t reload but does have a dependency that changes, allowing it to somewhat listen to changes and act accordingly.
For a basic example, consider the computed property count
:
<template> <div class="hello"> <h1>{{ count }}</h1> </div> </template> <script> export default { name: "HelloWorld", data() { return { shopNumber: 2 } }, computed: { count: function() { return 'The shop number is ' + this.shopNumber } } }; </script>
The count
property receives the this.shopNumber
as a dependency from the data
function, then returns a sentence containing the this.shopNumber
and it’s made available directly to the template.
You can use computed properties to solve more complex problems. Let’s detail a few more use cases in which Vue.js computed properties come in handy.
Computed properties are great for filtering data. For instance, let’s say you’re filtering an array from an input search bar.
In the data
function below, we have an array, userData
, containing information we want to display in the component, but we also need to allow the user to filter what is displayed by searching with an input tag (bound with the data
property searchQuery
). All this is done within the computed property resultQuery
:
export default { name: "HelloWorld", data() { return { userData: [ { image: "https://pbs.twimg.com/profile_images/1347769407892811786/fJyOAatX_400x400.jpg", name: "Tunde", uid: "LfhxERlvyfh2auIY0HnpidjJg3L2", }, { name: "bola", image: "https://pbs.twimg.com/profile_images/1355220122512863234/0NZI8bzI_400x400.jpg", uid: "R6lyXuNwZfc9ztLDfIZBSZLg2QD2", }, { uid: " k8ZVBdA9wfetiB8vJV3Qc07NZty1", image: "https://pbs.twimg.com/profile_images/1321720900274868224/w5iM_Ads_400x400.jpg", name: "Supreme", }, ], searchQuery: null }; }, computed: { resultQuery() { if (this.searchQuery) { return this.userData.filter((item) => { return this.searchQuery .toLowerCase() .split(" ") .every((v) => item.name.toLowerCase().includes(v)); }); } else { console.log(this.userData); return this.userData; } }, }, };
In our template, searchQuery
is bound to the search input tag and the data returned from th resultQuery
is looped to be displayed in the component.
<template> <div> <input v-model="searchQuery" type="text" placeholder="Search the name"> <div class="Chatroom__list__messages" v-for="result in resultQuery" :key="result.image" > <div class="Chatroom__list__messages__img"> <img :src="result.image" /> </div> <div class="Chatroom__list__messages__message"> <div class="Chatroom__list__messages__message__name"> <div class="Chatroom__list__messages__message__name__indi"> {{result.name}} </div> <div class="Chatroom__list__messages__message__name__time"> yesterday </div> </div> <div class="Chatroom__list__messages__message__details"> message from supreme </div> </div> </div> </div> </template>
Basically, resultQuery
checks whether the user has typed anything in the input
tag bound to searchQuery
. Then, it filters with the userData.name
. If the user hasn’t searched anything, it returns the entire userData
array.
I’ve created a live example on CodeSandbox.
In the same vein, we can use computed properties to handle calculations. All we need to do is pass the dependency into the property, write the calculation we need it to execute, then return the answer:
<script> export default { name: "ComputedCalculation", data() { return { number: 2 } }, computed: { totalMarks() { return this.number * 2; } } }; </script>
We have a computed property totalMarks
where we pass in a dependency (number
) from the data
function and multiply it by two:
<template> <div class="hello"> <h1>{{ totalMarks }}</h1> </div> </template>
Here’s a live example.
In our template, we simply call the computed property name within it and the value displays in the component. This might seem like a relatively simple example, but imagine you’re building a financial calculator and dealing with multiple dependencies and more complex calculations, such as compound interest:
Compound Interest = P [(1 + i)n – 1]
Where:
P
is principali
is nominal annual interest rate in percentage termsn
is number of compounding periodsWriting this formula directly into your template is not good for code readability, and it’s definitely not scalable.
v-if
You can use computed properties to check whether a condition is true, then use v-if
within our template to determine whether to display a block of code or not.
Here, the displayBoolean
is set to true
by default and is set as a dependency to the computed property display
. Within display
, we can check whether the display property is true
. If it is, then we return true
; otherwise, we return false
:
<script> export default { name: "HelloWorld", data() { return { displayBoolean: true } }, computed: { display() { if(this.displayBoolean) { return true } else return false } } }; </script>
The result from display
is fed into the v-if
in our template to determine whether the block of code will be displayed or hidden. We then create a button to toggle the value of displayBoolean
for demonstration purposes:
<template> <div class="hello"> <h2 v-if="display">Display conditionally</h2> <button @click="displayBoolean = !displayBoolean">Toogle</button> </div> </template>
mapGetters
Considering we’re using mapGetters
, we can use computed properties to access the data retrieved from our getters.
In the example below, we rename our getter getChatInfo
to chatData
and return the data within the getter through our chatInfo
computed property:
<script> import { createNamespacedHelpers } from "vuex"; const { mapGetters } = createNamespacedHelpers("chat"); export default { name: "Chat", computed: { ...mapGetters({ chatData: "getChatInfo", }), chatInfo() { console.log(this.chatData); return this.chatData; }, }, }; </script>
<template> <div class="hello"> <h1>{{ chatInfo.name }}</h1> <h1>{{ chatInfo.message }}</h1> </div> </template>
Although rather unorthodox, you can also use computed properties to set data rather than just retrieve data as a computer getter.
We can define a computed setter like this:
<script> export default { name: "HelloWorld", data () { return { firstName: "" } }, computed: { theFullName: { get () { return `${this.firstName}` }, set (fullName) { this.firstName = fullName } } } }; </script>
theFullName
is a computed property that has the ability to set data by binding the computed property to the content of an input
tag using v-model
. Here, we manipulate the value of the data property firstName
by typing and seeing it change in real time:
<template> <div class="hello"> <h1>{{ theFullName }} </h1> <input v-model="theFullName" type="text"> </div> </template>
Check out a live example.
To put we’ve learned into practice, let’s create a shopping cart in Vue.js that allows the user to pick the quantity of an item they want, calculate the cost of multiple items, and calculate the total including shipping fees.
Note: For the sake of demonstrating computed properties, the code for this example app may not look entirely DRY.
Each item has a fixed price of $5.00. The user selects the quantity they need, and this is then bound to the computed property quantity
, which acts as both a getter and setter. The total price of each item (quantity * unit price) is calculated in a computed property called priceCalc
. This process is replicated for the second item with quantity2
and priceCalc2
:
<script> export default { name: "HelloWorld", props: { msg: String }, data() { return { qty: 1, price: 5, qty2: 1, price2: 5, showTotal: false } }, computed: { quantity: { get() { return `${this.qty}` }, set(theQuantity) { this.qty = theQuantity } }, priceCalc () { return this.qty * this.price }, quantity2: { get() { return `${this.qty2}` }, set(theQuantity) { this.qty2 = theQuantity } }, priceCalc2 () { return this.qty2 * this.price2 }, subtotal () { return this.priceCalc + this.priceCalc2 }, shipping () { return (2 * 10)/ this.subtotal || '' } }, methods: { switchView() { this.showTotal = !this.showTotal } } }; </script>
The addition of the total cost of individual items is done in the computed property subtotal
, and shipping
is calculated using the same pattern. total
is the sum of all the costs including shipping.
We have a button
that hides and shows our subtotal
, shipping
, and total
. This is done by having a data property showTotal
set to false
and toggling it within the method
switchView
. Clicking the button
triggers the switchView
function.
Computed properties and methods in Vue.js might seem interchangeable, but technically they affect Vue apps differently.
Computed properties cache results, meaning a computed property only executes once after the component is mounted except for any of its dependency changes. A method, meanwhile, executes every time that method is called in the component.
Computed properties and methods have different use cases. It often depends on whether you want a function to execute every time regardless of dependency.
Imagine, for example, that you have a Math.random()
within a function and you want it to reload every time. In this case, you’d need to use a method instead of a computed property.
Caching helps improve performance by reducing the number of reloads and requests the application needs to make.
Computed properties are pretty much a necessity in Vue.js because they allow you to read and write cleaner, scalable, and more readable code.
Now that you understand some basic use cases for computed properties, I’d encourage you to read the official Vue.js documentation and explore further on your own to see what you can do with computed properties in Vue.js.
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps, including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
One Reply to "Understanding computed properties in Vue.js"
Good write up.
Please, I am new to vue, and thus seek for your assistance.
Concerning the shopping cart example, I am stuck with a situation where you would have to send the “total” price of the product to the database. As the total price is calculated in the computed property, but then not sent to the “data” property, how can it be sent to the database? Thank you for your assistance.