在vue.js开发中,我们很多时候都会用到模板语法(例1):
<div id="app">
<p>字符串:{{ message }}</p>
<p>字符串长度:{{ message.split('').length }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Steven'
}
})
</script>
这里会显示出字符串以及它的长度:
我们可以看到字符串的长度是通过模板里的message.split(’’).length计算得出的,但是这些计算的逻辑其实并不应该直接写在模板里,因为太多的逻辑会使得模板难以阅读和维护,这时候就可以用到我们的computed和methods来解决了,修改后的代码如下(例2):
<div id="app">
<p>字符串:{{ message }}</p>
<p>字符串长度:{{ message1 }}</p>
<p>字符串长度:{{ message2() }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'Steven'
},
computed: {
message1: function () {
return this.message.split('').length;
}
},
methods: {
message2: function () {
return this.message.split('').length;
}
}
})
</script>
在例2中,我们计算字符串长度的逻辑不再写在模板里了,而是分别通过computed和methods两个途径去实现:
第一个方法用到了computed,computed就是计算属性,我们先声明了一个message1的计算属性,提供的函数将会变成app.message1的getter 函数,因此当我们在获取message1的时候,相当于调用了它去计算字符串的长度,然后返回作为app.message1的值。
另外我们也可以通过在模板中调用方法来显示同样的结果,定义在methods里的逻辑跟computed的逻辑是一模一样的。
综上所述,computed和methods的相同点就是,它们都可以通过相同的逻辑去实现相同的结果,所以在表面上看他们是一样的。
但实际上他们的原理却不一样,computed是响应式的,methods并非响应式。
怎么理解这句话呢?看下面的例子(例3):
<div id="app">
<p>字符串:{{ message }}</p>
<p>computed:</p>
<p>字符串长度:{{ message1 }}</p>
<p>字符串长度:{{ message1 }}</p>
<p>methods:</p>
<p>字符串长度:{{ message2() }}</p>
<p>字符串长度:{{ message2() }}</p>
</div>
<script>
var count1 = 0;
var count2 = 0;
var app = new Vue({
el: '#app',
data: {
message: 'Steven'
},
computed: {
message1: function () {
return '第' + ++count1 + '次执行:' + this.message.split('').length;
}
},
methods: {
message2: function () {
return '第' + ++count2 + '次执行:' + this.message.split('').length;
}
}
})
</script>
在例3里面,我们在访问了message1 两次的同时,也调用了两次message2,在这过程中,count1 和count12起到了计数器的作用,我们可以发现,虽然访问了message1两次,但是count1并没有计算两次,因为computed是基于它们的响应式依赖进行缓存的,只要message的值没有发生变化,不管访问多少次message1,message1返回的结果都不会变;相对地,我们调用了两次message2,count2就计算了两次,这说明methods里的方法每次触发渲染的时候,都会执行其中的函数。
总结
我们在开发中什么时候用computed,什么时候用methods呢,这取决于逻辑的运算量和执行时机,例如我们声明的计算属性计算量非常大,而且它被访问的次数非常多,改变的时机却很少,那么就需要用computed了,因为缓存会让我们减少很多计算量,如果没有缓存,每次都调用方法的话,那么我们每调用一次都需要运算一次结果,尽管这个结果一直没有被改变,这就不利于性能优化了。