Vue中的方法与计算


178

Vue.js中的方法和计算值之间的主要区别是什么?

它们看起来相同且可互换。



1
@xDreamCoding您链接的答案确实确实是在解决这个问题,但绝不是这个问题的重复。另外它更出名。
罗曼·文森特

请参阅文档,其中有关“计算属性与方法”标题的内容对此主题进行了详细介绍:vuejs.org/v2/guide/computed.html
Kshitij Dhyani

Answers:


242

Vue中的计算值和方法有很大不同,在大多数情况下绝对不能互换。

计算财产

计算值更合适的名称是计算属性。实际上,当实例化Vue时,将使用getter有时是setter将计算出的属性转换为Vue的属性。基本上,您可以将计算值视为派生值,只要用于计算它的基础值之一被更新,它就会自动更新。您不调用计算的,也不接受任何参数。您引用的是计算属性,就像引用数据属性一样。这是文档中的经典示例:

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

在DOM中这样引用:

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

计算值对于处理Vue上存在的数据非常有价值。每当您要过滤或转换数据时,通常都将为此目的使用计算值。

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

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

计算值也将被缓存,以避免重复计算在未更改时不需要重新计算的值(例如,可能不在循环中)。

方法

方法只是绑定到Vue实例的函数。仅当您显式调用它时,才会对其进行评估。像所有javascript函数一样,它接受参数,并且每次调用时都会重新评估。在任何情况下,函数都有用的方法是有用的。

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的文档非常好,并且易于访问。我推荐它。


1
如果用户有两个输入,如从c到f的温度转换,反之亦然,则两个输入都可以确定彼此的值。请参阅albireo.ch/temperatureconverter,这两个输入会自动作出反应,而无需按下转换按钮。哪一种最适合使用计算或方法?
Bootstrap4

2
对于特定的 UI,其中输入之间具有循环关系,我将使用方法。codepen.io/Kradek/pen/gROQeB?editors=1010
Bert

2
@ Bootstrap4虽然,这也是一个带有计算的对象,但是它比较复杂。codepen.io/Kradek/pen/gROQeB?editors=1010
Bert

3
>方法...仅在您显式调用它时才会被评估。不符合此视频的规定:youtube.com/watch?v=O14qJr5sKXo
Cameron Hudson

2
@CameronHudson在视频示例中,对方法进行了评估,因为它们已在template中明确引用。这是一个说明差异的示例。请注意,如果在模板中显式引用了数据,则仅在数据更改时才调用方法。
Bert

60

@gleenk要求提供一个实际的例子来表明方法和计算属性之间的缓存和依赖关系差异,我将展示一个简单的场景:

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

在这里,我们有2个方法和2个计算属性执行相同的任务。方法addToAmethodaddToBmethod与所计算的属性addToAcomputedaddToBcomputed所有附加20(即,age值)对任一ab。至于方法,它们称为已经上执行的操作时间任何列出的属性,即使一个特定方法的依赖并没有改变。对于计算出的属性,仅当依赖项已更改时才执行代码;例如,引用A或B的特定属性值之一将分别触发addToAcomputedaddToBcomputed

方法和计算的描述似乎很相似,但是正如@Abdullah Khan已经指定的那样它们不是一回事!现在,让我们尝试添加一些html来一起执行所有操作,看看它们的区别在哪里。

方法案例演示

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>

解释的结果

当我单击按钮“添加到A”时,将调用所有方法(请参见上面的控制台日志屏幕结果),该addToBmethod()方法也将执行,但是我没有按下“添加到B”按钮;引用B的属性值未更改。如果我们决定单击“添加到B”按钮,则会出现相同的行为,因为同样会独立于依赖项更改来调用这两种方法。在这种情况下,这是一种不好的做法,因为即使没有更改依赖关系,我们也会每次执行这些方法。这确实是资源消耗,因为没有用于未更改的属性值的缓存。

方法 按钮方式

计算属性案例演示

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>

解释的结果

当我单击“添加到A”按钮时,仅addToAcomputed调用了计算属性,因为,正如我们已经说过的那样,仅当依赖项已更改时,才执行计算属性。而且由于我没有按下按钮“添加到B”并且B的age属性值没有更改,因此没有理由调用和执行计算的属性addToBcomputed。因此,从某种意义上讲,计算出的属性像一种缓存一样,为B属性保持“相同”值。在这种情况下,这是一种很好的做法

计算的 计算按钮


3
为什么按下1个按钮时所有方法都被执行?原因/逻辑是什么?
Bsienn

1
@Bsienn是个好问题:原因是Vue基本上不知道哪个方法需要运行,具体取决于更新的内容。这就是计算属性执行的操作,它们监视需要计算或重新计算的变量,并且仅在需要时运行。
Giulio Bambini

2
以及使用方法的原因是什么?看来计算的属性好一些(假设我们正在谈论“获取”方法)……
user3529607

5
@ user3529607,但计算的属性不接收参数。
Rodion Golovushkin '18年

3
@ user3529607据我了解,安装或创建Vue实例时,方法可能会很有用。使用计算属性无法做到这一点。同样,我们必须返回计算属性的值。
Dhaval Chheda

13

来自 docs

..computed属性根据其依赖关系进行缓存。仅当某些依赖项已更改时,计算属性才会重新评估。

另一方面,如果您想缓存数据,请使用计算属性,而如果您不希望缓存数据,请使用简单的Method属性。


1
嗨,您能写一个有用的例子来说明实际用途的差异吗?
Davide De Maestri

@gleenk我将添加一个实际示例,向您展示方法与计算属性之间的缓存/依赖关系差异。希望您会感激。
朱利奥·班比尼

谢谢@GiulioBambini
Davide De Maestri

7

计算与方法之间的差异之一。假设我们有一个将返回计数器值的函数(counter只是变量)。让我们看看函数在计算方法中的行为

已计算

第一次执行时,函数内部的代码将被执行,并且vuejs将计数器值存储在缓存中(以加快访问速度)。但是,当我们再次调用函数vuejs时,将不会再次执行该函数内部编写的代码。它首先检查是否对计数器进行了任何更改。如果进行了任何更改,则仅它将重新执行该函数内部的代码。如果没有更改计数器,则vuejs将不会再次执行该功能。它只会从缓存中返回先前的结果。

方法

就像javascript中的常规方法一样。每当我们调用该方法时,它将始终在函数内部执行代码,而与对计数器所做的更改无关。

无论代码中的更改如何,方法将始终重新执行代码。仅当其中一个依赖项的值发生更改时,计算的内容才会重新执行代码。否则,它将为我们提供缓存中的先前结果,而无需重新执行


6

这是该问题的细分。

何时使用方法

  • 对DOM中发生的某些事件做出反应
  • 当组件中发生某些事情时调用函数。
  • 您可以从计算的属性或观察程序中调用方法。

何时使用计算属性

  • 您需要从现有数据源中组合新数据
  • 您有一个在模板中使用的变量,该变量是根据一个或多个数据属性构建的
  • 您希望将复杂的嵌套属性名称简化为更易读和易于使用的名称(但是在原始属性更改时进行更新)
  • 您需要从模板中引用一个值。在这种情况下,最好创建一个计算属性,因为它已缓存。
  • 您需要聆听多个数据属性的更改

2

计算属性

计算属性也称为计算值。这意味着它们会更新,并且可以随时更改。同样,它缓存数据,直到数据更改为止。实例化Vue时,将计算出的属性转换为属性。

我还想分享一件事:您无法在计算属性中传递任何参数,这就是为什么在调用任何计算机属性时都不需要括号的原因。

方法

方法与函数相同,并且工作方式相同。此外,方法不执行任何操作,除非您调用它。而且,像所有javascript函数一样,它接受参数,并且每次调用时都会重新评估。之后,他们将无法缓存值

在调用括号的方法中,您可以在其中发送一个或多个参数。


0

偶然发现了同样的问题。对我来说更像这样:

  1. 当Vue.js看到v-on directive后跟一个方法时,它确切知道要调用哪个方法以及何时调用它。
<button v-on:click="clearMessage">Clear message</button> // @click
// method clearMessage is only called on a click on this button

<input v-model="message" @keyup.esc="clearMessage" @keyup.enter="alertMessage" />
/* The method clearMessage is only called on pressing the escape key
and the alertMessage method on pressing the enter key */
  1. 当被调用的方法没有v-on directive它会被称为每次触发事件时,更新的DOM页面上(或只是需要重新渲染页面的一部分)。即使该方法与事件被触发无关。
<p>Uppercase message: {{ messageUppercase() }}</p>
methods: {
   messageUppercase() {
      console.log("messageUpercase");
      return this.message.toUpperCase();
   }
}
/* The method `messageUppercase()` is called on every button click, mouse hover 
or other event that is defined on the page with the `v-on directive`. So every
time the page re-renders.*/
  1. 当更改其函数定义中的this单词所引用的属性值时,才调用 Computed属性。
<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 is only called when the propery message is
changed. Not on other events (clicks, mouse hovers,..) unless of course a specific 
event changes the value of message.  */

这里的好处是,如果computed未使用调用方法,则最佳做法是使用属性v-on directive

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.