Vue.js中的方法和计算值之间的主要区别是什么?
它们看起来相同且可互换。
Vue.js中的方法和计算值之间的主要区别是什么?
它们看起来相同且可互换。
Answers:
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的文档非常好,并且易于访问。我推荐它。
@gleenk要求提供一个实际的例子来表明方法和计算属性之间的缓存和依赖关系差异,我将展示一个简单的场景:
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个计算属性执行相同的任务。方法addToAmethod
&addToBmethod
与所计算的属性addToAcomputed
&addToBcomputed
所有附加20(即,age
值)对任一a
或b
。至于方法,它们都称为每已经上执行的操作时间任何列出的属性,即使一个特定方法的依赖并没有改变。对于计算出的属性,仅当依赖项已更改时才执行代码;例如,引用A或B的特定属性值之一将分别触发addToAcomputed
或addToBcomputed
。
方法和计算的描述似乎很相似,但是正如@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属性保持“相同”值。在这种情况下,这是一种很好的做法。
来自 docs
..computed属性根据其依赖关系进行缓存。仅当某些依赖项已更改时,计算属性才会重新评估。
另一方面,如果您想缓存数据,请使用计算属性,而如果您不希望缓存数据,请使用简单的Method属性。
计算与方法之间的差异之一。假设我们有一个将返回计数器值的函数(counter只是变量)。让我们看看函数在计算和方法中的行为
已计算
第一次执行时,函数内部的代码将被执行,并且vuejs将计数器值存储在缓存中(以加快访问速度)。但是,当我们再次调用函数vuejs时,将不会再次执行该函数内部编写的代码。它首先检查是否对计数器进行了任何更改。如果进行了任何更改,则仅它将重新执行该函数内部的代码。如果没有更改计数器,则vuejs将不会再次执行该功能。它只会从缓存中返回先前的结果。
方法
就像javascript中的常规方法一样。每当我们调用该方法时,它将始终在函数内部执行代码,而与对计数器所做的更改无关。
无论代码中的更改如何,方法将始终重新执行代码。仅当其中一个依赖项的值发生更改时,计算的内容才会重新执行代码。否则,它将为我们提供缓存中的先前结果,而无需重新执行
这是该问题的细分。
何时使用方法
何时使用计算属性
偶然发现了同样的问题。对我来说更像这样:
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 */
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.*/
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
。