computed计算属性
不重复做的原则
一个数据在模板中的很多地方都使用了,如果要改某个数据属性,那就要把所有地方都重改一遍。
data(){user:{email:'fangfang',nickname:'方方',phone:'11828284876'}},template:`<div>{{user.nickname||user.phone||user.email}}</div>{{user.nickname||user.phone||user.email}}`
用computed可以解决这个问题,displayName是根据其他属性计算而来的属性。
computed:{displayName(){const user = this.userreturn user.nickname||user.phone||user.email}},template:`<div>{{displayName}}</div>{{displayName}}`
要修改属性,可以用key:function;也可以用get和set
get和set方式来修改:
data(){user:{email:'fangfang',nickname:'方方',phone:'11828284876'}},computed:{displayName:{ //注意这里变成对象了get(){const user = this.userreturn user.nickname||user.phone||user.email},set(value){this.user.nickname = value}}}
computed的缓存
如果依赖的属性没有变化,就不会重新计算
getter/setter默认不会做缓存,Vue做了特殊处理
watch监听
用途:当数据变化时,执行一个函数。也就是根据数据的变化做一些其他操作。
注意:watch是不监听第一次的值的。就是出生时的值。
撤销例子
new Vue({data(){n:0,history:[],inUndoMode:false},watch:{n(newValue,oldValue){if(!this.inUndoMode){this.history.push({from:oldValue,to:newValue})}}},template:`<div>{{n}}<button @click="add1">+1</button><button @click="add2">+2</button><button @click="minus1">-1</button><button @click="minus2">-2</button><hr/><button @click="undo">撤销</button></div>`,methods:{add1(){this.n += 1},add2(){this.n += 2},minus1(){this.n -= 1},minus2(){this.n -= 2},undo(){const last = this.history.pop()const old = last.fromthis.inUndoMode = truethis.n = old//$nextTick是达到setTimeout的效果,是vue提供给watch异步时使用的this.$nextTick(()=>{this.inUndoMode = false},0)}}}).$mount("#app")
下面是watch模拟computed的例子,说实话,这样做很傻!
handle()是处理变化的。immediate:true表示第一次也运行一下。
new Vue({data(){user:{email:'fangfang@qq.com',nickname:'方方',phone:'13817274638'},displayName:''},watch:{'user.email':{handler(){const {user:{email,nickname,phone}} = thisthis.displayName = nickname || email || phone},immediate:true},'user.phone':{handler(){const {user:{email,nickname,phone}} = thisthis.displayName = nickname || email || phone},immediate:true},'user.nickname':{handler(){const {user:{email,nickname,phone}} = thisthis.displayName = nickname || email || phone},immediate:true}},tempplate:`<div>{{displayName}}<button @click="user.name=undefined">remove nickname</button></div>`,methods:{changed(){const user = this.userthis.displayName = user.nickname || user.email || user.phone}}}).$mount("#app")
小结
computed和watch都是在数据变化时执行一个函数。computed注重于依赖之间的变化和缓存。watch着重于变化时执行什么东西,而不是得出一个结果。
watch 的 deep 选项
首先看一个例子,
改变obj.a时,obj.a变了,obj还是原来的地址,所以obj没变
改变obj时,obj变了,但obj.a没变
new Vue({data(){n:0,obj:{a:'a'}},template:`<div><button @click="n += 1">n+1</button><button @click="obj.a += 'hi'">obj.a + 'hi'</button><button @click="obj = {a:'a'}">obj + 新对象</button></div>`,watch:{n(){console.log("n 变了")},obj(){console.log("obj 变了")},"obj.a":function(){console.log("obj.a 变了")}}}).$mount("#app")
简单类型看值,复杂类型(对象)看地址。
deep:true是深入进去看,表示监听obj里的所有属性
new Vue({data(){n:0,obj:{a:'a'}},template:`<div><button @click="n += 1">n+1</button><button @click="obj.a += 'hi'">obj.a + 'hi'</button><button @click="obj = {a:'a'}">obj + 新对象</button></div>`,watch:{n(){console.log("n 变了")},obj(){handle(){console.log("obj 变了")},deep:true //表示修改obj.a时,obj也变了},"obj.a":function(){console.log("obj.a 变了")}}}).$mount("#app")
watch的完整用法
注意:watch内不要用箭头函数,因为this指向问题。
语法一:
watch:{o2:function(value,oldValue){},o3(){},04:[f1,f2],o5:'methodName',o6:{handler:fn,deep:true,immediate:true},'object.a':function(){}}
语法二:
vm.$watch('xxx',fn,{deep:..,immediate:..})
computed和watch的区别
computed是计算属性,watch是监听意思。
computed是用来计算出一个值的,不用加括号,当作属性一样用;会根据依赖的进行自动缓存,依赖的属性不变就读取缓存,不会重新计算。
watch有两个选项,immediate和deep。deep表示监听一个对象时,是否要观察对象里面属性的变化。immediate设定第一次是否也监听。
资料来源:饥人谷
