一、什么是计算属性
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。
比如,我们在一个Vue实例里面设置data,myname的值为tom。这个值是未经过处理的,所以在页面上显示tom。
<div id="box">
{{myname}}
</div>
var vm = new Vue({
el:"#box",
data:{
myname:"tom"
}
但现在我们的要求是需要在页面上呈现首字母大写的姓名。我们可以在双大括号的模板里进行处理。
<div id="box">
{{myname.substring(0,1).toUpperCase()+myname.substring(1)}}
</div>
可以看出这样会造成模板非常复杂,难以更改和维护,可读性差,所以需要我们使用Vue的计算属性。
二、计算属性的使用
计算属性写在Vue实例之中的computed选项内,最终返回计算后的结果。
<div id="box">
<p>{{getMyName}}</p>
</div>
var vm = new Vue({
el:"#box",
data:{
myname:"tom"
},
computed:{
getMyName() {
return this.myname.substring(0,1).toUpperCase()+this.myname.substring(1)
}
}
这样就成功在computed属性中完成了对属性的计算。
改变data值,计算属性也会重新计算,重新渲染界面。
在控制台输入vm.myname=‘jack’,改变myname的值,可以看到:
计算属性将jack更改为Jack,并且重新渲染在界面上。
这个例子是改变字符串,如果不够直观,我们可以看一个操作加法的例子。
<div id="app">
<button @click="add()">给num1加1</button>
<p>计数{{getSum}}</p>
</div>
var app = new Vue({
el:"#app",
data:{
num1:{
count:1
},
num2:{
count: 10
}
},
computed:{
getSum(){
return this.num1.count+this.num2.count
}
},
methods:{
add(){
this.num1.count++
}
}
})
我们用add方法改变了num1的count值,计算属性也会相应做出改变。可以看到,计算属性可以依赖多个Vue 实例的数据。只要其中任一数据变化,计算属性就会重新执行计算。
一个Vue实例的计算属性也可以依赖其他Vue实例的数据。
三、计算属性缓存
回到一开始的例子
<div id="box">
<p>使用计算属性:{{getMyName}}</p>
<p>使用方法:{{getMyNameWithMethod()}}</p>
</div>
var vm = new Vue({
el:"#box",
data:{
myname:"tom"
},
computed:{
getMyName() {
console.log("计算属性调用")
return this.myname.substring(0,1).toUpperCase()+this.myname.substring(1)
}
},
methods:{
getMyNameWithMethod() {
console.log("方法调用")
return this.myname.substring(0,1).toUpperCase()+this.myname.substring(1);
}
}
})
可以看到,计算属性与方法都可以实现我们的操作。使用方法时需要加上(),而计算属性就像属性一样使用双大括号调用。
计算属性更优越的地方在于计算属性可以实现缓存。
我们现在将计算属性与方法分别都调用两次。
<div id="box">
<p>使用计算属性:{{getMyName}}</p>
<p>使用方法:{{getMyNameWithMethod()}}</p>
<p>使用计算属性:{{getMyName}}</p>
<p>使用方法:{{getMyNameWithMethod()}}</p>
</div>
可以看到控制台中显示,计算属性只调用一次,而方法调用了两次。计算属性计算后会进行缓存,再次调用时直接使用缓存数据,效率提高。计算属性只有在他的相关依赖发生改变的时候才会重新求值。
我们现在改变myname的值,看出计算属性因为数据的更改重新计算。而此时方法已经调用了4次。当在遍历一个大的数组以执行很多操作时,频繁调用方法,就会导致大量不必要的运算。
四、监听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:监听属性watch,它监听的是data中的各个属性。
<div id="app">
<input type="text" v-model="msg">
<h3>{{msg}}</h3>
</div>
new Vue({
el:"#app",
data(){
return {
msg:''
}
},
watch:{
msg:function(newMsg,oldMsg){
console.log(newMsg,oldMsg);
if(newMsg === 'hello'){
console.log("你好,我监听到了")
}
}
})
在我们输入hello的过程中,控制台实时监听到我们的输入,并且显示新旧值。
watch是对基本数据类型的简单监听。当我们需要监听对象、数组等复杂数据类型时,就需要深度监视。
<div id="app">
<h4>{{stu[0].name}}</h4>
<button @click="stu[0].name = 'tom'">改变</button>
</div>
new Vue({
el:"#app",
data(){
return {
stu:[{name:'jack'}]
}
},
watch:{
stu:{
deep:true,
handler:function (newV,oldV){
console.log(newV[0].name)
}
}
}
})
在需要监听的stu对象中把deep的值写为true,这样当我们点击按钮改变stu对象中数组的值的时候,就会执行handler这个方法。