Vue:计算属性
Vue:计算属性
- 计算属性
- get
- set
在模板中,有时候填入的值要依赖于多个属性计算得出。
例如使用姓和名拼出全名:
以上效果可以通过以下代码实现:
<div id="root">姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>全名:<span>{{firstName}}-{{lastName}}</span> <br/><br/>
</div><script type="text/javascript">
new Vue({el:'#root',data:{firstName:'张',lastName:'三',}
})
</script>
把输入框与数据进行双向绑定,在<span>
内部进行模板渲染。这样当然没有问题,但是如果需要更加复杂的字符串拼接,就会很复杂。
除此之外,也可以通过在methods
内部创建方法,最后直接调用方法得到字符串:
new Vue({el:'#root',data:{firstName:'张',lastName:'三'},methods: {fullName(){return this.firstName + '-' + this.lastName}}
})
在fullName
方法中,完成字符串拼接并返回,最后直接在模板中调用方法:
全名:<span>{{fullName()}}</span>
使用函数,可以处理更加复杂的情况,但是这样效率很低。
当模板中任意一个变量更新,模板中所有表达式都会被重写计算,如果firstName
和lastName
以外的属性改变了,也会调用fullName
方法,但是结果是不变的。
示例:
<div id="root">other:<input type="text" v-model="other"> <br/><br/>姓:<input type="text" v-model="firstName"> <br/><br/>名:<input type="text" v-model="lastName"> <br/><br/>全名:<span>{{fullName()}}</span>
</div><script type="text/javascript">new Vue({el:'#root',data:{other: '其它',firstName:'张',lastName:'三'},methods: {fullName(){const name = this.firstName + '-' + this.lastNameconsole.log("fullName更新为 " + name)return name}}})
</script>
现在增加了一个额外的other
属性以及一个输入框,与other
进行双向绑定。
每次调用fullName
,都会输出自己被调用了,以及更新后的名称。
多次修改other
框内部的内容:
此时fullName
调用了18
次,但是每一次fullName
的值都是一样的,这会导致效率降低。
计算属性
为了兼顾效率以及复杂数据的处理,Vue
推出了计算属性。
语法:
new Vue({computed:{计算属性:{// 函数}}
})
在computed
属性内部,可以配置多个计算属性,这些计算属性有get
和set
方法,方法内可以使用data
的值,来进行字符串拼接,数值计算等复杂行为。最后返回一个值,作为属性使用。
get
比如对姓名的拼接:
new Vue({el:'#root',data:{firstName:'张',lastName:'三',},computed:{fullName:{get(){return this.firstName + '-' + this.lastName}}}
})
以上代码定义了一个fullName
计算属性,它的get
方法返回一个拼接字符串,此处的this
就是Vue
实例,在实例下查找firstName
和lastName
,并拼接成值返回。
那么这个fullName
计算属性如何使用?
既然叫计算属性,那么这就是一个属性,可以在模板中直接使用:
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
计算属性最后也会被挂载到Vue
实例下,与data
下的属性用起来没有区别。
这种计算属性在效率上有两个优势:
- 在一次模板更新中,只会计算一次计算属性
- 只有计算属性依赖的其他属性改变,计算属性才会更新
在模板中,使用多次fullName
:
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
输出结果:
可以看到,每次修改firstName
和lastName
,只会调用一次fullName
方法,如果是之前的methods
的方式实现字符串拼接,那么每次更新都会调用四次方法。
这是因为每次更新时,会把计算属性放到缓存中,如果后续再次遇到使用计算属性的地方,直接去缓存取用。
和之前一样,加一个无关的输入选项:
other:<input type="text" v-model="other"> <br/><br/>
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
首先更新姓名,正常调用fullName
了,后续更新other
的值,不再触发fullName
方法了。
因为other
属性不是fullName
依赖的属性,这个属性更新时不会重新计算fullName
,这带来了很大的效率提升。
set
除了可以使用data
下已有的数据计算值,计算属性还可以实现双向数据绑定,这依赖于set
方法。
示例:
new Vue({el:'#root',data:{firstName:'张',lastName:'三',},computed:{fullName:{get(){return this.firstName + '-' + this.lastName},set(value){console.log('set 被调用',value)const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}}}
})
以上代码给fullName
定义了一个set
方法,只要fullName
被改变,就会反过来修改firstName
和lastName
的值。
由于规定输入值必须是firstName-lastName
,此时使用-
作为分隔符进行split
,再设置到this.firstName
和this.lastName
中。
修改一下HTML
样式:
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<input type="text" v-model="fullName"> <br/><br/>
为fullName
也进行了双向数据绑定,这样就可以修改fullName
的值了。
输出结果:
在下面的框把张-三
改为李-四
,调用了两次set
,并且上面的输入框的值也改变了,说明成功通过fullName
反向影响了firstName
和lastName
的值。
总结一下:
- 计算属性可以基于现有的
data
内的属性,进行复杂的计算,返回一个值 - 计算属性也是一个属性,可以直接在模板访问
- 计算属性效率比
mthods
高,只有依赖的属性被修改,才会调用,一次模板更新,最多计算一次计算属性 - 计算属性可以设置
set
,反过来影响依赖的data
下的属性
最后,计算属性还有简写形式,如果计算属性没有set
方法:
new Vue({computed:{fullName:{get(){return this.firstName + '-' + this.lastName}}}
})
此时可以把get
方法一起省略,计算属性本身作为一个方法:
new Vue({computed:{fullName(){return this.firstName + '-' + this.lastName}}
})
两者是等效的。