计算属性
以姓名案例为例
目标需求:输入姓,名,页面自动输出全名,以’-‘分隔
可用实现方法:
1.原生实现
let p = {
firstname:'张',
lastname:'三'
}
Object.defineProperty(p,'fullname',{
set(value){
const arr = value.split('-');
this.firstname = arr[0];
this.lastname = arr[1];
},
get(){
return this.firstname + '-' + this.lastname;
}
})
复制代码
当要追加的属性是由其他已有属性加工而来时,使用defineProperty方法。
defineProperty方法中,当fullname属性被调用,则触发get函数,当fullname属性被更改,则会触发set函数,通过设置set函数内部代码可以反过来改变原对象的属性。
Vue的源码中数据监测就是基于set和get函数。
2.插值方法
<div id="root">
姓:<input type="text" v-model="firstname">
名:<input type="text" v-model="lastname">
<span>全名:{{firstname + '-' + lastname}}</span>
</div>
<script>
new Vue({
el:'#root',
data:{
firstname:'张',
lastname:'三'
}
})
</script>
复制代码
当只需要计算全名显示全名时可以使用插值方法实现。
3.methods实现
<div id="root">
姓:<input type="text" v-model="firstname">
名:<input type="text" v-model="lastname">
<span>全名:{{getFullName()}}</span>
</div>
<script>
new Vue({
el:'#root',
data:{
firstname:'张',
lastname:'三'
},
methods:{
getFullName(){
return this.firstname + '-' + this.lastname;
}
}
})
复制代码
4.Computed计算属性实现
const vm = new Vue({
el:'#root',
data:{
firstname:'张',
lastname:'三'
},
computed:{
fullName:{
set(value){
const arr = value.split('-');
this.firstname = arr[0];
this.lastname = arr[1];
},get(){
return this.firstname + '-' + this.lastname;
}
}
}
})
复制代码
如果只需要计算全名,那么可以将computed属性简写成
fullName(){return this.firstname + '-' + this.lastname;}
因为想要进一步实现更改全名同步改变姓或者名的功能,因此使用完整写法,即调用了set和get函数。其中set函数会获取到更改后的值。
注意:computed中的fullName属性是vm对象在调用,因此它的this指的都是Vue对象。
比较methods实现和computed实现:
通过methods实现时,全局数据只要发生一点变化,methods中的方法都会被调用一次。
而通过computed实现时,只有依赖的属性发生改变时,才会重新调用computed中的方法。
与methods相比,computed拥有缓存机制,效率更高。
数据监视
以姓名案例为例
姓名案例的watch实现
<div id="root">
姓:<input type="text" v-model="firstname">
<br><br>
名:<input type="text" v-model="lastname">
<br><br>
<span>全名:{{fullname}}</span>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
firstname: '张',
lastname: '三',
fullname: ''
},
watch: {
firstname: {
immediate: true, //若immediate为true,则初始化时就会调用一次
handler(newValue, oldValue) {
this.fullname = newValue + '-' + this.lastname;
}
},
lastname(newValue, oldValue) {
this.fullname = this.firstname + '-' + newValue;
}
}
})
</script>
复制代码
handler函数是完整写法,是为了可以添加immediate属性,使初始化时调用一次watch。如果不需要初始化调用,那么可以进行简写。
watch中的handler函数可以检测到对应数据的变化,并返回新值和旧值,这一点与computed很相似,但是computed中的set函数貌似无法返回旧值(?)总的来说,computed可以实现的功能watch都可以实现,但是watch可以实现的功能computed可能无法实现,比如watch可以异步完成(定时器),但是要注意,定时器的函数一定要写成箭头函数,否则函数内部的this会指向window。
watch可以被封装到Vue的外部,使用vm.$watch('属性',{})
可以用来应对一开始没有决定监测哪个对象的情况。
Vue中一个很重要的原则:
所有被Vue管理的函数,都不要写箭头函数 例如:computed和watch中的函数。
所有不被Vue管理的函数,都要写箭头函数 — 例如:定时器的回调,ajax的回调。