Can you explain the primary distinction between a method
and a computed
property in Vue.js?
I'm finding it tricky to differentiate between the two as they appear quite similar.
Can you explain the primary distinction between a method
and a computed
property in Vue.js?
I'm finding it tricky to differentiate between the two as they appear quite similar.
When it comes to Vue, the distinction between computed values and methods is crucial. They are not generally interchangeable.
Computed Property
In Vue, a computed value is better referred to as a computed property. Upon instantiation of Vue, computed properties are essentially converted into Vue properties with getter and sometimes setter functions. Essentially, a computed value is a derivative that automatically updates whenever its underlying values change. You don't "call" a computed property; instead, you reference it just like any other data property. Take this example from the official documentation:
computed: {
// a computed getter
reversedMessage: function () {
// `this` refers to the Vue instance
return this.message.split('').reverse().join('')
}
}
In the DOM, it would be referenced like this:
<p>Computed reversed message: "{{ reversedMessage }}"</p>
Computed values are incredibly useful for manipulating data within your Vue instances, especially when filtering or transforming data.
data:{
names: ["Bob", "Billy", "Mary", "Jane"]
},
computed:{
startsWithB(){
return this.names.filter(n => n.startsWith("B"))
}
}
<p v-for="name in startsWithB">{{name}}</p>
Additionally, computed values are cached to prevent unnecessary re-calculations of unchanged values, such as those found in loops.
Method
On the other hand, a method in Vue simply equates to a function bound to the Vue instance. It executes only upon explicit invocation. Like standard JavaScript functions, methods can accept parameters and will be recalculated every time they are called. Methods serve the same purpose as any regular function.
data:{
names: ["Bob", "Billy", "Mary", "Jane"]
},
computed:{
startsWithB(){
return this.startsWithChar("B")
},
startsWithM(){
return this.startsWithChar("M")
}
},
methods:{
startsWithChar(whichChar){
return this.names.filter(n => n.startsWith(whichChar))
}
}
The Vue documentation is exceptionally well-crafted and easy to navigate. I highly recommend exploring it.
Addressing the request made by @gleenk for a practical example illustrating the differences between cache and dependencies in methods versus computed properties, I will demonstrate a straightforward scenario:
new Vue({
el: '#vue-app',
data: {
a: 0,
b: 0,
age: 20
},
methods: {
addToAmethod: function(){
console.log('addToAmethod');
return this.a + this.age;
},
addToBmethod: function(){
console.log('addToBmethod');
return this.b + this.age;
}
},
computed: {
addToAcomputed: function(){
console.log('addToAcomputed');
return this.a + this.age;
},
addToBcomputed: function(){
console.log('addToBcomputed');
return this.b + this.age;
}
}
});
In this setup, there are two methods and two computed properties designed to achieve the same outcome. The methods addToAmethod
& addToBmethod
, as well as the computed properties addToAcomputed
& addToBcomputed
, all add +20 (i.e., the value of age
) to either a
or b
. While the methods get invoked every time an action occurs on any of the listed properties, even if the dependencies remain unchanged, the computed properties execute their code only when a dependency actually changes.
Although the method and computed descriptions may seem similar, it's essential to understand that they serve different purposes – as clarified by @Abdullah Khan here. Let's incorporate some HTML to see how these distinctions play out together.
new Vue({
el: '#vue-app',
data: {
a: 0,
b: 0,
age: 20
},
methods: {
addToAmethod: function(){
console.log('addToAmethod');
return this.a + this.age;
},
addToBmethod: function(){
console.log('addToBmethod');
return this.b + this.age;
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VueJS Methods - stackoverflow</title>
<link href="style.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.min.js"></script>
</head>
<body>
<div id="vue-app">
<h1>Methods</h1>
<button v-on:click="a++">Add to A</button>
<button v-on:click="b++">Add to B</button>
<p>Age + A = {{ addToAmethod() }}</p>
<p>Age + B = {{ addToBmethod() }}</p>
</div>
</body>
<script src="app.js"></script>
</html>
Upon clicking the "Add to A" button, all methods get triggered, including addToBmethod()
, even though the "Add to B" button wasn't pressed. This redundant execution of methods, irrespective of dependency changes, is considered inefficient and resource-intensive due to the absence of caching for unchanged property values.
new Vue({
el: '#vue-app',
data: {
a: 0,
b: 0,
age: 20
},
computed: {
addToAcomputed: function(){
console.log('addToAcomputed');
return this.a + this.age;
},
addToBcomputed: function(){
console.log('addToBcomputed');
return this.b + this.age;
}
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>VueJS Computed properties - stackoverflow</title>
<link href="style.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.11/vue.min.js"></script>
</head>
<body>
<div id="vue-app">
<h1>Computed Properties</h1>
<button v-on:click="a++">Add to A</button>
<button v-on:click="b++">Add to B</button>
<p>Age + A = {{ addToAcomputed }}</p>
<p>Age + B = {{ addToBcomputed }}</p>
</div>
</body>
<script src="app.js"></script>
</html>
Clicking the "Add to A" button triggers only the computed property addToAcomputed
, demonstrating the efficiency of computed properties by executing them solely upon relevant dependency changes. This proactive behavior prevents unnecessary computations, optimizing performance and promoting good coding practices.
Let's delve into the details of this inquiry.
Instances when methods are used
Situations where computed properties come in handy
According to the documentation
Computed properties are cached based on their dependencies, meaning they will only re-evaluate when those dependencies change.
If you want data to be cached, utilize Computed properties. On the other hand, if you prefer data not to be cached, stick with simple Method properties.
One key distinction between computed properties and methods is how they handle re-execution of code. Consider a function that returns a counter value (where "counter" is just a variable). Let's examine the behavior of this function in both a computed property and a method.
Computed Property:
When a computed property is first executed, the code inside the function runs and Vue.js stores the result in a cache for quick access. Upon subsequent calls to the function, Vue.js does not immediately rerun the code. Instead, it checks if any changes have been made to the counter. Only if there are changes will it re-execute the code within the function. If no changes have been made, Vue.js simply returns the previous result from the cache.
Method:
A method behaves like a regular JavaScript method. Every time it is called, the code inside the function is executed regardless of any changes to the counter.
In summary, a method will always reexecute its code, regardless of changes, while a computed property only reexecutes its code when one of its dependencies has changed. Otherwise, it retrieves the previous result from the cache without rerunning the code.
Understanding Computed Properties
Computed properties, also known as computed values, have the ability to both update and change at any given time. Additionally, they store data in a cache until it is altered. When Vue is initialized, computed properties are transformed into regular properties.
It's important to note that computed properties do not accept parameters, therefore no parentheses are required when calling them.
Distinguishing Methods
Methods are similar to functions and operate in the same manner. However, a method will only execute when explicitly called upon. Unlike computed properties, methods can accept parameters and will be recalculated each time they are invoked. They do not retain cached values.
When invoking a method, parentheses are necessary and you have the option to pass one or more parameters within them.
Encountered a similar question and I found it easier to understand this way:
v-on directive
along with a method, allowing it to determine which specific method to execute and when to execute it.<button v-on:click="clearMessage">Clear message</button> // @click
// The clearMessage method will only be triggered upon clicking this button
<input v-model="message" @keyup.esc="clearMessage" @keyup.enter="alertMessage" />
/* The clearMessage method triggers upon pressing the escape key,
while the alertMessage method gets called upon pressing the enter key */
v-on directive
, it will be executed each time an event alters the DOM on the page (or necessitates re-rendering). This occurs even if the method is unrelated to the event causing the change.<p>Uppercase message: {{ messageUppercase() }}</p>
methods: {
messageUppercase() {
console.log("messageUpercase");
return this.message.toUpperCase();
}
}
/* The `messageUppercase()` method is triggered on every button click, mouse hover,
or other events specified with the `v-on directive` on the page. Hence, it executes
whenever the page requires re-rendering.*/
this
keyword within its function definition.<p>Uppercase message: {{ messageUppercase }}</p>
data() {
return {
message: "I love Vue.js"
}
},
computed: {
messageUppercase() {
console.log("messageUpercase");
return this.message.toUpperCase();
}
}
/* The computed property messageUppercase gets triggered solely when the message
property changes. It doesn't respond to other events like clicks or hovers unless
those events modify the message value. */
The key point here is to utilize computed
properties when a method isn't called via the v-on directive
.
When working with the Vue Composition API, which is included in Vue 3 and available as a plugin for Vue 2, the syntax for methods and computed properties differs from the traditional Vue syntax:
For example :
Computed Properties :
Computed properties are functions that by default take a getter callback as a parameter and return an immutable ref based on other properties like ref, reactive, or store state.
import {computed, ref} from 'vue'
export default {
setup() {
const count = ref(0);
const doubleCount = computed(() => count.value * 2)
return {count, doubleCount} // expose the properties to the template
}
}
Methods :
These are plain JavaScript functions that behave similarly in both Vue and Vanilla JS. They are exposed to the template and used as event handlers. It's not recommended to use them for rendering purposes, as it can lead to issues like infinite rendering loops.
import {computed, ref} from 'vue'
export default {
setup() {
const count = ref(0);
const doubleCount = computed(() => count.value * 2)
function increment() {
ref.value++
}
return {count, doubleCount, increment} // expose the properties/functions to the template
}
}
The distinction :
Computed Properties :
Methods :
I'm here to provide additional insights based on the information shared by other members. The example provided has helped me grasp the concept of computed properties thoroughly, and I aim to clarify it further in my response.
When you need to modify data, it's essential to utilize methods. On the other hand, if you want to adjust the representation of existing data, computed properties come into play. By practicing both concepts, you'll gradually develop a comfort level with using them efficiently. Here are some key points to remember:
Upon reviewing the content or executing the sample code, you'll notice that changes made to values presented in computed properties (via methods, user input, or other means) trigger recalculation and caching. However, each time a method is invoked, it will be executed regardless of the outcome (e.g., in the provided scenario, when a value reaches zero, the computed property ceases to be recalculated).
// Your Vue instance
new Vue({
el: '#app',
data: {
infinity: Infinity,
value: 3,
debt: -6,
cash: 9,
moneyInBank: 15,
},
// Computed properties for calculating remaining funds
computed: {
computedPropRemainingCashFundsIfPaid: function() {
console.log('computedPropRemainingCashFundsIfPaid');
return this.debt + this.cash;
},
computedPropRemainingTotalFunds: function() {
console.log('computedPropRemainingTotalFunds');
return this.cash + this.moneyInBank + this.debt;
}
},
methods: {
// Method to deposit funds
depositFunds: function(from, to, value, limit = false) {
if (limit && (this[to] + value) >= 0) {
this[from] += this[to];
this[to] = 0;
} else if (this[from] > value && this[from] - value >= 0) {
this[to] += value;
this[from] -= value;
} else {
this[to] += this[from];
this[from] = 0;
}
},
// Method to repay a debt
repayADebt: function() {
this.value = Math.abs(this.value);
if (this.debt < 0) {
this.depositFunds('cash', 'debt', this.value, true);
}
console.log('Attempt to repayADebt', this.value);
},
// Method to lend an amount
lendAmount: function() {
this.depositFunds('infinity', 'debt', -Math.abs(this.value));
console.log('Attempt to lendAmount', this.value);
},
// Method to withdraw funds
withdraw: function() {
if (this.moneyInBank) {
this.depositFunds('moneyInBank', 'cash', this.value);
}
console.log('Attempt to withdraw', this.value);
}
}
});
* {
box-sizing: border-box;
padding: 0;
margin: 0;
overflow-wrap: break-word;
}
html {
font-family: "Segoe UI", Tahoma, Geneva, Verdana;
font-size: 62.5%;
}
body {
margin: 0;
font-size: 1.6rem;
}
#app {
margin: 3rem auto;
max-width: 50vw;
padding: 1rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
}
label,
input {
margin-bottom: 0.5rem;
display: block;
width: 100%;
}
label {
font-weight: bold;
}
ul {
list-style: none;
margin: 1rem 0;
padding: 0;
}
li {
margin: 1rem 0;
padding: 1rem;
border: 1px solid #ccc;
}
.grid {
display: grid;
grid: 1fr / 1fr min-content 1fr min-content;
gap: 1rem;
align-items: center;
margin-bottom: 1rem;
}
.grid> :is(button, input) {
height: 3rem;
margin: 0;
}
.computed-property-desc {
padding: 1rem;
background-color: rgba(0, 0, 0, 0.3);
text-align: justify;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>A First App</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="app">
<h1>Computed Properties Guide</h1>
<p style="background-color: bisque;">
Let's assume that you have <span v-once>{{ cash }}</span>$; And you need to pay a debt=<span v-once>{{ debt }}</span>
</p>
<p>Your bank account: {{ moneyInBank }}$ <button v-on:click="withdraw(value)">Withdraw {{ value }}$ from
bank</button></p>
<p>Your cash: {{ cash }}$</p>
<p>Your debt: {{ debt }}$ <button v-on:click="lendAmount(value)">Borrow {{ value }}$ from Infinity</button></p>
<div class="grid">
<button v-on:click="repayADebt(value)">Repay a debt</button>
<span>in amout of</span>
<input type="text" v-model.number="value">
<span>$</span>
</div>
<p>computedPropRemainingCashFundsIfPaid/<br><mark>Available funds in case of debt repayment</mark> = {{ computedPropRemainingCashFundsIfPaid }}$</p>
<p>computedPropRemainingTotalFunds = {{ computedPropRemainingTotalFunds }}$</p>
<p class="computed-property-desc">Remember, when data needs to be altered, employ methods; while computed properties are meant for modifying data representations. Familiarize yourself with both paradigms to discern their appropriate usage. Key takeaways:
1. Always ensure computed properties return a value;
2. Use them exclusively for transforming data without manipulating its original form for presenting purposes.</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b1c7c4d4f130eee4eef3e4">[email protected]</a>/dist/vue.js"></script>
</body>
</html>
VueJs documentation provides a straightforward explanation:
One key difference is that a method will execute the function every time there's a re-render.
On the other hand, a computed property will only update when its reactive dependencies have been altered.
According to the Vue3 documentation, computed properties are cached based on their reactive dependencies, while methods will always run the function whenever a re-render happens.
The end result of both approaches is the same, but the way they handle reactivity differs between computed properties and methods.
For more information, you can also check out these additional links:
One distinct contrast between computed properties and methods lies in their execution behavior. In computed properties, the function is triggered only when there is a change in the input values, while methods execute the function every time they are invoked regardless of any changes.
Vue.js provides developers with two distinct ways to generate data based on component state: methods and computed properties. Although they both serve the purpose of producing data, they operate differently:
Methods: These functions are declared within the methods
section of a Vue component. Methods are re-evaluated every time a re-render occurs, regardless of whether their dependencies have changed or not. They are ideal for tasks that need to be executed each time a specific event takes place, such as handling a button click.
Computed Properties: Defined in the computed
section, computed properties are more efficient for computations that rely on reactive data. Vue keeps track of their dependencies (reactive properties they depend on) and only recalculates them when one of these dependencies changes. This makes computed properties well-suited for computations that do not require execution on every re-render, particularly when the computation is resource-intensive or the output is utilized in multiple areas within the template.
The key difference lies in their reactivity and caching behavior: methods execute without caching upon each invocation, whereas computed properties cache their results and solely recalculate when their dependencies alter, making them more efficient for transforming reactive data.
I have successfully stored my visitors' style sheet preference in a cookie, but I am facing an issue with sharing the cookie across subdomains. Even after specifying the domain, the cookie does not seem to be shared. What could be causing this proble ...
For certain goals I have set up in Google Analytics, I am unable to use the JavaScript tracking. Instead, I am interested in achieving the same result by making a call with PHP. One solution that seems straightforward to me is to invoke the URL of the tra ...
I've been attempting to figure out a solution for moving a specific array within another array to the beginning. The problem I'm encountering is that the code I was using, as suggested in a previous question, only removes the last value and plac ...
As I navigate my way through the world of React as a newcomer, I've encountered a challenge that I need some advice on. I am attempting to add a new key and value to an array of objects, but I'm struggling to accomplish this task. Can anyone prov ...
Dealing with a dynamically changing table columns can be tricky. This means that hardcoding the template for the table like this example won't work: <template> <v-data-table :headers="headers" :items="items" hide-actions cl ...
We have a unique solution that utilizes multiple Single Page Applications (SPAs) developed in both Angular and AngularJS. These applications integrate the oidc-client-js library for authentication with Identity Server 4. However, due to limitations of Angu ...
Having some issues with Vue.js transitions. Works strangely in Chrome and not at all in Microsoft Edge. Hard to explain, so I've included a link to my code on JSFiddle for reference: link : my code /* animation*/ .slide-fade-enter-active, .slide-fade ...
My goal is to extract data from another sheet in the same spreadsheet and present it as a dropdown selection in the sidebar. The code.gs file contains a function called getVisualData() that successfully retrieves the desired list: function getVisualData() ...
I have a string formatted like this: ItemName1:Rate1:Tax1_ItemName2:Rate2:Tax2:_ItemName3:Rate3:Tax3_ItemName4:Rate4:Tax4 (and so on, up to item 25). My task is to take an index provided by the user (for example, 2), retrieve the item at that index when ...
In my Vue.js application, I have implemented a login system. The main script in my main.js file includes the necessary imports and configurations: import Vue from 'vue'; import NProgress from 'nprogress'; import Resource from 'vue ...
Recently I started exploring Angular/Fire and decided to test out some of its features by creating a basic app. Firestore and authentication were working smoothly, but when I attempted to include Storage, an error message popped up: ERROR FirebaseError: ...
As a beginner in Angular, my current task involves loading data from a JSON file upon click, which I have successfully achieved so far. However, I am facing an issue where I'm unable to load the first JSON object before clicking, meaning that I want ...
Consider the scenario where I need to generate a list of li elements: {map(listItems, (obj,i) => <li key={i}> <a target="_blank" href={obj.itemName === 'view_detail' ? `event/${id}` : ''} > <i c ...
Secrets of the JavaScript Ninja provides an interesting example: HTML <button id="test">Click me!</button> JavaScript var button = { clicked: false, click: function() { this.clicked = true; console.log("this:", this, ...
Is there a way to remove an item from an array by its value rather than index, while ensuring compatibility with IE8? Any assistance would be greatly appreciated. Thank you. Below is the array in question: var myArray = ['one', 'two', ...
Is there a way to reset or clear the values of two select boxes after refreshing the page in CodeIgniter? Currently, both select boxes retain their values after a refresh. Below is the code I am using: <?php echo form_dropdown('cat_id', $ ...
I'm trying to access a specific attribute called "data-price". Any tips on how I can retrieve the value of this attribute using this syntax: Preferred Syntax div[0].id: 48ms // appears to be the quickest method Alternative Syntax - Less Efficient ...
Our website utilizes ExpressionEngine as the CMS and Magento's cart for e-commerce. I am encountering challenges with cookies and their accessibility in various sections. A cookie is used for storing search selections, allowing users to return to our ...
There are various Bootstrap 4 themes available that simplify the process of styling and laying out a website. Some of these themes require specific organization of our assets folders. For example: root-folder/ ├── assets/ │ ├── css/ │ ...
I have a vue application running on an apache server within a virtual environment. Express is being run with nodemon. When attempting to log in, I am encountering the following error message: Cannot read property 'status' of undefined xhr.js:160 ...