通常我们会在模板中绑定表达式,模板是用来描述视图结构的。
如果模板中的表达式存在过多逻辑,模板会变得臃肿不堪,维护变得非常困难。
因此为了简化逻辑,当某个属性的值依赖于其他属性的值时,我们可以使用计算属性。
1. 什么是计算属性
计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新,与之相关的 DOM 部分也会同步自动更新
<div id="example">
"text" v-model = 'a'>
"text" v-model = 'b'>
a = {{ a }}, b = {{ b }}, cont = {{ cont }}
div>
var vm = new Vue({
el: '#example',
data: {
a: 1,
b: 2
},
computed: {
// 一个计算机属性的 getter
cont: function () {
// this 指向 vm 实例
return this.a + this.b
}
}
})
从上例可以看出,当 vm.a 和 vm.b 的值发生变化时,vm.cont 的值会自动更新,并且会同步更新到 DOM 部分
前面实例只提供了 getter,实际上除了 getter 我们还可以设置计算属性的 setter
var app = new Vue({
el: '#example',
data: {
a: 'hah',
b: 'waw',
},
computed: {
cont: {
// 一个计算属性的 getter
get : function(){
// this 指向 vm 实例
return this.a + " "+ this.b
},
// 一个计算属性的 setter
set : function( newVal ){
var names = newVal.split(' ')
this.a = name [0]
this.b = name [1]
}
}
}
})
当 设置 vm.cont 的值时,vm.a和vm.b 的值也会自动更新
2. 计算属性缓存
+ 如果在计算属性方法中执行大量的耗时操作,会影响性能。例如:在计算属性 getter 中循环一个大的数组以执行很多操作,那么当频繁调用该计算属性时,就会导致大量不必要的运算
+ Vue 只有在计算属性依赖的属性值发生了改变时才会重新执行 getter
+ 这样也存在一个问题,就是只有 vue 实例中被观察的数据属性发生了改变时才会重新执行 getter。但是有时候计算属性依赖实时的非观察数据属性
"app"> {{ example }}
var vm = new Vue({
el: '#app',
data: {
welcome :'welcome to china!'
},
computed: {
example: function (){
return Date.now() + this.welcome
} }
})
我们需要每次在访问 example 时都取得最新事件而不是缓存时间。vue 还默认提供了缓存开关,在计算属性对象中指定 cache 字段来控制是否开启缓存。代码示例:
var vm = new Vue({
el :'#app',
data: {
welcome: 'welcome to china!'
},
computed: {
example: {
// 关闭缓存,默认为 true
cache : false,
get : function (){
return Date.now() + this.welcome
}
}
}
})
4. 常见问题
当包含计算属性的节点被移除并且模板中其他地方没有在引用该属性时,那么对应的计算属性 getter 不会执行:
div id="example">
if = 'show'> total price = {{ totalprice}}
当点击按钮使 show 为 false 时,此时 p 元素会被移除,在 p 元素内部的计算机属性 totalprice 的 getter 方法不会被执行,但是当计算属性一直出现在模板中时,getter 方法还是会被执行
<div id="example">
<button @click = 'toggleShow'> toggle show total price button>
<p> {{ totalprice}} p>
<p v-if = 'show'> total pirce = {{ totalprice}} p>
div>
var items = [
{ number:1,text:'one'},
{ number:2,text:'two'}
]
var vm = new Vue({
el: '#app',
data: {
items : items
},
components : {
'my-item' : {
replace :true,
computed : {
fulltext : function(){
return 'item' + this.text
}
}
}
}
})