Method vs Computed in Vue

2020-01-25 03:12发布

问题:

What is the main difference between a method and a computed value in Vue.js?

They look the same and interchangeable.

回答1:

Computed values and methods are very different in Vue and are definitely not interchangeable in most cases.

Computed Property

A more appropriate name for a computed value is a computed property. In fact, when the Vue is instantiated, computed properties are converted into a property of the Vue with a getter and sometimes a setter. Basically you can think of a computed value as a derived value that will be automatically updated whenever one of the underlying values used to calculate it is updated. You don't call a computed and it doesn't accept any parameters. You reference a computed property just like you would a data property. Here's the classic example from the documentation:

computed: {
  // a computed getter
  reversedMessage: function () {
    // `this` points to the vm instance
    return this.message.split('').reverse().join('')
  }
}

Which is referenced in the DOM like this:

<p>Computed reversed message: "{{ reversedMessage }}"</p>

Computed values are very valuable for manipulating data that exists on your Vue. Whenever you want to filter or transform your data, typically you will use a computed value for that purpose.

data:{
    names: ["Bob", "Billy", "Mary", "Jane"]
},
computed:{
    startsWithB(){
        return this.names.filter(n => n.startsWith("B"))
    }
}

<p v-for="name in startsWithB">{{name}}</p>

Computed values are also cached to avoid repetitively calculating a value that doesn't need to be re-calculated when it hasn't changed (as it might not be in a loop for example).

Method

A method is just a function bound to the Vue instance. It will only be evaluated when you explicitly call it. Like all javascript functions it accepts parameters and will be re-evaluated every time it's called. Methods are useful in the same situations any function is useful.

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(whichCharacter))
    }
}

Vue's documentation is really good and easily accessible. I recommend it.



回答2:

As @gleenk asked for a practical example to make evident the cache and dependency differences between methods and computed properties, I'll show a simple scenario:

app.js

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;
        }
    }
});

Here we have 2 methods and 2 computed properties that perform the same task. The methods addToAmethod & addToBmethod and the computed properties addToAcomputed & addToBcomputed all add +20 (i.e. the age value) to either a or b. Regarding the methods, they are both called every time an action has been performed on any of the listed properties, even if the dependencies for one specific method have not changed. For the computed properties, the code is executed only when a dependency has changed; for example, one of the specific property values that refers to A or B will trigger addToAcomputed or addToBcomputed, respectively.

The method and computed descriptions seem pretty similar, but as @Abdullah Khan has already specified it, they are not the same thing! Now let's try to add some html to execute everything together and see where the difference is.

The Method case demo

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>

The explained result

When I click on the button "Add to A", all the methods are called (see the console log screen result above), the addToBmethod() is also executed but I didn't press the "Add to B" button; the property value that refers to B has not changed. The same behaviour comes if we decide to click the button "Add to B", because again both the methods will be called independently of dependency changes. According to this scenario this is bad practice because we are executing the methods every time, even when dependencies have not changed. This is really resource consuming because there is not a cache for property values that have not changed.

The Computed property case demo

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>

The explained result

When I click on the button "Add to A", only the computed property addToAcomputed is called because, as we already said, the computed properties are executed only when a dependency has changed. And since I didn't press the button "Add to B" and the age property value for B has not changed, there is no reason to call and execute the computed property addToBcomputed. So, in a certain sense, the computed property is maintaining the "same unchanged" value for the B property like a kind of cache. And in this circumstance this is consider good practice.



回答3:

From the docs

..computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed.

If you want data to be cached use Computed properties on the other hand if you don't want data to be cached use simple Method properties.



回答4:

One of difference between computed and method. Suppose we have a function which will return counter value.(counter is just variable). Let's look how function behaves in both computed and method

Computed

At first time of execution the code inside the function will be executed and vuejs will store the counter value in cache(for accessing faster). But when we are again calling the function vuejs will not again execute the code written inside of that function. It first checks any changes made to the counter or not. If any changes made then only it will re-execute the code which is inside that function. If there are no changes made to the counter vuejs will not again execute the function. It will simply return the previous result from the cache.

Method

This is just like a normal method in the javascript. Whenever we call the method it will always execute the code inside the function irrespective of changes made to the counter.

Method will always reexecutes the code irrespective of changes in the code. where as computed will reexecute the code then only if one of it's dependency's values changed. Otherwise it will give us the previous result from the cache without reexecuting



回答5:

Here’s a breakdown of this question.

When to use methods

  • To react to some event happening in the DOM
  • To call a function when something happens in your component.
  • You can call a method from computed properties or watchers.

When to use computed properties

  • You need to compose new data from existing data sources
  • You have a variable you use in your template that’s built from one or more data properties
  • You want to reduce a complicated, nested property name to a more readable and easy to use one (but update it when the original property changes)
  • You need to reference a value from the template. In this case, creating a computed property is the best thing, because it’s cached.
  • You need to listen to changes of more than one data property


回答6:

Computed Properties

Computed properties are called computed value as well. It means, they update and can be changed anytime. Also, it caches the data until it changes. When the Vue is instantiated, computed properties are converted into a property.

One more thing I want to share, You cannot pass any parameter in the computed properties that's why while calling any computer property no parenthesis required.

Methods

Methods are the same as function and work the same way. Besides, a method does nothing unless you call it. Also, like all javascript functions, it accepts parameters and will be re-evaluated every time it’s called. After that, they can’t cache values

In the method calling parenthesis is there and you can send one or more parameter in that.