1. 计算属性的定义
计算属性是vue实例中的一个配置选项:computed
所有的计算属性都以函数的形式写在vue实例内的computed选项内,最终返回计算后的结果。其依赖的数据变化才变化。
每一个计算属性都包含一个 getter 方法和一个 setter 方法。
(1)读取计算属性的值 , 默认调用方法getter方法
(2)当数据改变时,默认调用set方法
computed的属性可以被视为是 data 一样,可以读取和设值
需要注意的是,不是说我们更改了getter里使用的变量,就会触发computed的更新,前提是computed里的值必须要在模板里使用才行。
说明
当一些数据需要根据其它数据变化时,需要进行处理才能去展示,虽然vue提供了绑定数据表达式绑定的方式,但是设计它的初衷只是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护,对于一些比较复杂和特殊的计算有可能就捉襟见肘了,而且计算的属性写在模板里也不利于项目维护
computed主要的作用:
分离逻辑(模板和数据分离)
缓存值
双向绑定(getter,setter)
2.计算属性的基础用法
在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,通常里面都是一个个计算相关的函数 , 一般就是用来通过其他的数据算出一个新数据 , 只要最终返回一个计算出来的结果即可。
计算属性后面直接跟一个 function,使用计算属性的默认方法 getter 来读取,里面可以执行一些逻辑或者直接return返回的值
// 默认用法 getter 举例:
computed: {
prices: function(){
var prices = 0
for(let i=0; i<this.package.length; i++){
prices += this.package[i].price * this.package[i].count
}
return prices
},
fullName: function(){ // 直接return
return this.firstName + '-' + this.lastName
},
// 上面写法等同于
fullname: {
get: function(){
return this.firstname + '-' + this.lastname
},
}
需要时,也可以提供一个 setter 函数 , 当手动修改计算属性的值就像修改一个普通数据那样时,就会触发 setter函数,执行一些自定义的操作 。例如下显示全名。
// setter 用法 举例:
var App = new Vue({
el: '#naa',
data: {
firstName: 'Jay',
lastName: 'Chou'
},
computed: {
fullName: {
// 数据渲染时会自动调用get方法
get: function(){
return this.firstName + '-' + this.lastName
},
// 注意必须要传递参数,否则没有意义
// 数据变化时自动调用set方法
set: function(newValue){
var names = newValue.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
}
})
fullname = 'Jay-Chou' // 此时会调用set方法
若现在再运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName也会相应地被更新;进而会触发getter被调用。
// 延伸
可以点击事件触发seterr函数
<input type='text' v-model='textValue'>
//使用计算属性
{{reverseMessage}}
// 触发setter
<button @click='computedSet(textValue)'>set</button>
计算属性
computed{
reverseMessage:{
get:function(){
return this.textValue.split('').reverse().jion('')
},
set:function(message){
this.textValue = message + 'HELLO'
}
}
},
methods:{
computedSet(message){
this.reverseMessage = message
}
}
注意
绝大多数情况下,我们只会用默认的getter方法来读取一个计算属性,在业务中很少用到setter,所以在声明一个计算属性时,可以直接使用默认的写法
3.计算属性的高级用法
1.计算属性还可以依赖多个vue实例的数据,只要其中任一个数据变化,计算属性就会重新执行,视图也会更新。适用于比较费时的数据计算
2.当使用组件时,计算属性也经常用来 动态传递props。
小技巧
计算属性还有两个很实用的小技巧容易被忽略:
- 计算属性可以依赖其他计算属性;
- 计算属性不仅可以依赖当前 Vue 实例的数据,还可以依赖其他实例的数据。
4.计算属性的缓存
计算属性基于它们的依赖进行缓存的,只有相关依赖发生改变的时候才会重新求值,一般为响应式依赖
什么是响应式依赖,Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应
vue提供cache标识 , 设置cache为false可以关闭缓存
5.计算属性与methods的区别
计算属性一般就是用来通过其他的数据算出一个新数据,而且它有一个好处就是,它把新的数据缓存下来了,当其他的依赖数据没有发生改变,它调用的是缓存的数据,这就极大的提高了我们程序的性能。而如果写在methods里,数据根本没有缓存的概念,页面每渲染一次就重新执行,所以每次都会重新计算。
共同点
调用 methods 里的方法也可以与计算属性起到同样的作用。
区别
方法methods : 如果是调用方法,只要页面重新渲染,方法就会重新执行;若不需要渲染,则不需要重新执行。
计算属性computed:不管是否渲染,只要计算属性依赖的数据(缓存)未发生变化,就永远不变。
( 计算属性缓存是定义在计算属性 computed 里的。)
结论
(1)用计算属性可以实现的问题,在 methods 里定义一个方法也可以实现相同的效果,甚至该方法还可以接受参数,使用起来更灵活。
(2)既然使用 methods 就可以实现,那么为什么还需要计算属性呢?因为计算属性是基于它的依赖缓存的,一个计算属性所依赖的数据发生变化时,它才会重新取值,所以只要依赖的数据不改变,计算属性也就不更新。
何时使用二者
使用计算属性还是 methods 取决于是否需要缓存,当遍历大数组和做大量计算时,应当使用计算属性,除非不希望得到缓存;
当需要数据实时发生变化时,适合用 methods。
6.计算属性与watch的区别
1.触发条件不同
computed计算属性会依赖于使用它的data属性,只要是依赖的data属性值有变动,则自定义重新调用计算属性执行一次。
watch则是在监控的data属性值发生变动时,其会自动调用watch回调函数。
2.应用场景不同
执行异步操作,开销较大的操作,避免堵塞主线程,使用watch。
简单且串行返回的,使用computed
参考文章
https://www.jianshu.com/p/6a1a4b61a7f6
https://www.jianshu.com/p/56f337688d6b
具体应用
// 观察outerNext的变化,控制按钮是否禁止或启用
<div class="verify-btn">
<button @click="goToNext" :class="{opacity :!outerNext}" :disabled="!outerNext">下一步</button>
</div>
computed: {
outerNext() {
if(this.secondObj.TransAmt != '' && this.secondObj.TransType != '2') {
return true;
} else if(this.secondObj.TransType == '2' && this.secondObj.TransAmt != '') {
if(this.secondObj.BespokeType == '0' && this.secondObj.BespokeDate != '') {
return true;
} else if(this.secondObj.BespokeCycleType == '0' || this.secondObj.BespokeCycleType == '1') {
if(this.secondObj.BespokeCycle != '' && this.secondObj.BespokeBeginDate != '' && this.secondObj.BespokeEndDat != '') {
return true;
}
}
}
return false;
},
},
// computed也可以跟watch一样,检测data中某个数据的变化,如果数据发生变化,可以默认调用getter函数拿到变化后的新数据
// 例如 , 需要检测data中PayeeType数据的变化 (点击单选框切换个人和企业两个按钮)
<div>
<span>收款人类型</span>
// 在vant中通过v-model绑定值当前选中项的 name
<van-radio-group v-model="interThirdObj.PayeeType" @click.native="Sta">
<van-radio name="1" class="left-radio" checked-color="#009E96">企业</van-radio>
<van-radio name="0" checked-color="#009E96">个人</van-radio>
</van-radio-group>
</div>
interThirdObj:{
PayeeType: '1', //收款人类型 0-个人 1-企业
}
// 可以如下实现
computed: {
PayeeType() {
return this.interThirdObj.PayeeType
}
}
// 这样可以拿到切换后的新值
// 需要注意 , 并不一定是在模板字符串使用了data中的数据才需要computed ,
// 需要检测某个数据的变化就可以使用 , 它跟watch的作用类似 ,
// 区别在于watch是不断触发更新 , 而computed只有值更新后才触发一次