浅谈一下Vue里computed 和 watch 的区别:
Computed
需求一:data 里给出姓和名,要求展示完整的名字
new Vue({
data:{
firstName:'Jack',
lastName:'Lee'
},
computed:{
fullName(){
return this.firstName + this.lastName
}
},
template:`
<div>
{{fullName}}
</div>
`
}).$mount('#app')
由代码可知:
1.fullName的值是通过 firstName和lastName的值计算而来,所以computed是计算属性;
2.template里调用fullName的值,可以把fullName当成属性直接调用,不用加括号( )
需求二:光看名字还不行,还要能改名字
new Vue({
data:{
firstName:'Jack',
lastName:'Lee'
},
computed:{
fullName:{
get(){
return this.firstName + ' ' + this.lastName
},
set(val){
const names = val.split(' ')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
template:`
<div>
{{fullName}}
<button @click="change">改名字</button>
</div>
`,
methods:{
change(){
this.fullName = 'Tom Chen'
console.log('名字已更改')
}
}
})
这里注意一下区别:
computed:{
fullName(){...}
}
computed:{
fullName:{
get(){...},
set(){...}
}
}
由上可知,计算属性可以是一个函数,也可以是一个由getter和setter组成的对象;
computed 也可以和 methods 方法混合起来用;
get( ) 代表:你什么值都不传进来,那我就给你返回一个默认的值;
set( ) 代表:你传一个值进来, 那就把名字设置为你传的这个值;
通过这样的 getter 和 setter ,就可以让计算属性实现更改,点击按钮改名字时,计算属性的值会发生变化,重新计算,页面会对应的刷新。但是如果再点,页面就不会再刷新了,不会再屏幕空白一下再显示出来:这是因为计算属性的结果会被缓存,只有在它的相关依赖发生改变时才会重新计算,所以再点改名字,页面是不会刷新的;
Watch
Watch 是监听、观察的意思,作用是:当数据变化时,执行一个函数;
Watch属性可以是字符串、函数、对象、数组
拥有deep、immediate两个属性
实例一:
new Vue({
data:{
n:0,
obj:{
a:'hello'
}
},
template:`
<div>
<p>{{n}}</p>
<button @click="n += 1">n+1</button>
<p>{{obj.a}}</p>
<button @click="obj.a += 'World'">obj.a + 'World'</button>
<p>{{obj}}</p>
<button @click="obj = {b:'b'}">obj = 新对象</button>
</div>
`,
watch:{
n(){
console.log('n变了')
},
"obj.a"(){
console.log('obj.a变了')
},
obj(){
console.log('obj变了')
}
}
}).$mount('#app')
点击 n+1 按钮,打印 n变了
点击 obj.a + 'World' 按钮,打印出 obj.a 变了,但是没有打印 obj变了
点击 obj = 新对象 按钮,打印出 obj变了, 但是没有打印 obj.a 变了
由上可知:watch 的监听方式是:简单数据看值,复杂数据看地址;
那如果我想实现,我监听obj这儿对象,它里面的 obj.a 变了后,我也能知道,可以吗?
可以,这就要用到 deep 了:
deep
watch:{
n(){
console.log('n变了')
},
"obj.a"(){
console.log('obj.a变了')
},
obj(){
console.log('obj变了')
deep:true
}
}
加上 deep 选项后,我们再点击 obj.a + 'World' 按钮时,打印出 obj.a 变了,然后点 obj = 新对象 按钮时,会打印出:obj.a 变了,obj变了;
所以 deep:true 会监听到对象的所有内部属性,默认值为 false
immediate
new Vue({
data:{
firstName:'Jack',
lastName:'Lee',
fullName:''
},
watch:{
firstName:{
handler:'change'
}
},
/* 监听 firstName 属性,当 firstName 发生变化时,调用 change 函数,这个函数写在 methods里 */
template:`
<div>
{{fullName}}
<button @click=" firstName = 'Tom' ">改名字</button>
</div>
`,
methods:{
change(){
this.fullName = this.firstName + ' ' + this.lastName
}
}
}).$mount('#app')
运行代码后,页面上什么也没有,只有一个改名字按钮:
明明不是在 template 里写了 {{ fullName }}了吗?为什么屏幕上什么都没有?至少该有个 data 里的默认值:Jack Lee 吧?
这是因为 watch 不会监听第一次变化!
我们点击按钮后,出现了 @click 里写的值:
那我想第一次就有值行不行?不能让页面空着吧?
行,用 immdiate选项 :
wacth:{
firstName:{
handler:'change',
immediate:true
}
}
初始页面就变成了我们原先设想的那样:
也就是,当 immediate:true 时,回调函数会在监听开始后立即执行;
总结
computed是计算属性,watch是监听、观察;
computed是用来计算一个值的,这个值我们在调用的时候不用加括号,直接当属性用就行;
computed根据依赖会自动缓存,如果依赖没变,computed就不会重新计算;
wacth是当监听的数据变化时,执行一个函数;
wacth里有两个选项,deep 和 immediate:deep 为真时就代表如果监听一个对象,还会监听对象里的属性变化,immediate表示在第一次渲染时,是否执行这个函数;