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.user
return 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.user
return 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.from
this.inUndoMode = true
this.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}} = this
this.displayName = nickname || email || phone
},
immediate:true
},
'user.phone':{
handler(){
const {user:{email,nickname,phone}} = this
this.displayName = nickname || email || phone
},
immediate:true
},
'user.nickname':{
handler(){
const {user:{email,nickname,phone}} = this
this.displayName = nickname || email || phone
},
immediate:true
}
},
tempplate:`
<div>
{{displayName}}
<button @click="user.name=undefined">remove nickname</button>
</div>
`,
methods:{
changed(){
const user = this.user
this.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设定第一次是否也监听。
资料来源:饥人谷