进阶属性
1.响应式原理
- options.data
1.会被 Vue 监听
2.会被 Vue 实例代理
3.每次对 data 的读写都会被 Vue 监控
4.Vue 会在data 变化时 更新 UI - 那么:data 变化时除了更新UI还能做点什么?
2.computed-计算属性
- 用途
1.被计算出来的属性就是计算属性
2.函数当做属性用,可以直接访问其 return 的值
3.要进行属性的读写:get 和 set
//用户名显示
new Vue({
data:{
user:{
email:"liuz.....com"
nickname:"刘"
phone:"138xx..xxx"
}
},
computed:{
display(){
const user = this.user
return user.nickname || user.email || user.phone
}
},
template:`
<div>
{{displayName}}
</div>
`
})
- 计算属性:可以让是其他属性计算而来的结果变成一个属性
1.默认会去读这个属性的返回值
2.列表选择展示:是通过列表user和用户的选择计算出来的
3.会让逻辑更加清晰,每个属性只用管自己就行了 - 缓存
当依赖的属性发生变化,则计算属性会重新计算一次
如果依赖的属性没有变化,那么计算属性就不会再算一次
——依赖的属性:computed中的计算属性 return 属性依赖的属性
3.Watch - 监听/侦听
- 用途
1.当数据变化时,执行一个函数
——computed也差不多:当属性变化时,计算出一个新的属性
2.例1:撤销
3.例2:模拟computed(不要模拟,有显示用computed)
//从this中解析出user,然后从user中解析email,nickname,phone
//二次解析后user不存在了,后面三个变量可以直接使用
const {user:{email,nickname,phone} = this}
- 4watch里面可以是函数,也可以是对象
1.函数:可以省掉冒号和function
2.对象:里面可以有多个函数
watch:{
n(){
console.log('n 变了')
}
}
- watch是异步的
1.异步:会等当前把代码执行完了再执行watch
2.watch的异步不是setTimeout,而是this.$nextTick函数
3.二次异步:异步后面跟一个异步,则是要按照异步的顺序来进行(前提:两个异步函数类型同一个)
undo(){//撤销
this.inUndoMode = true
this.n = old //watch是异步的,要undo执行完才执行
this.$nextTick(()=>{
//异步后面跟一个异步,那就按照顺序watch执行完执行该句
this.inUndoMode = false
},0)
}
- watch默认第一次的值不监听
因为第一次的值不是变化,而是从无到有 - 如何展示第一次的值?
watch:{
'user.email':{ //监听第二层的属性方法
handler(){//处理器:监听到变化执行函数
const {user:{email,nickname,phone}} = this
this.displayName = nickname || email || phone
},
immediate:true//第一次也运行一下
}
}
- computed和watch都是在数据变化的时候执行一个函数
1.computed着重于:依赖之间的变化以及缓存,判断是否重新计算结果
2.watch着重于:变化的时候去执行什么东西,而不是得出一个结果,有可能什么结果都没有
3.1 变化
- 对于Vue来说,何谓变化?
1.对于对象来说:对象存储的是地址,只有对象变成了一个新的对象,也就是地址变了,那么对象才变了
2.对象里面的属性变了,对象地址没变,那么对象没变
2注意:如果是对象变了,但对象里面的某些属性没有变,那么那些属性就没有变化(看中的是value的变化) - 简单类型看值,复杂对象(看地址)
- 其实就是
===
原则 - 问题:能否做到对象里面任意属性变了,对象就变了
答:使用一个Vue选项deep:true
,deep的意思是监听 object 的时候是否往深了看
这样就不用监听对象里面的所有属性了
watch:{
obj:{
handler(){
console.log('obj 变了')
},
deep: true //只要obj里面有属性变了,那么obj变了
}
}
3.2 watch的完整用法
- watch用法
- 类型:
{ [key: string]: string | Function | Object | Array }
- 注意:不要使用箭头函数来定义watch
因为:箭头函数里面的this是全局对象,window或者global,JS的箭头函数没有this,它就只能继承外面的this - 用法一:
1.函数:function接收vue传过来的两个参数,value是最新值最新,oldVlue是以前的值
2.数组:数组里面两个函数,o3变化的时候依次执行两个函数
3.方法:会去methods里面找对应的名字
4.对象:要执行的函数;是否往深了看;第一次是否运行
5.obj.a:第二层属性监听
watch:{
o1:function(value,oldValue){},
o2(){},
o3:[f1,f2]
o4:'methodName',
o5:{
handler:fn,
deep:true,
immediate:true
}
'obj.a':function(){}
}
- 用法二:(尽量用方法一)
vm.$watch('xxx',fn,{deep:...,immediate:...})
但是这个是写在new Vue外面的,想要放到里面怎么办?
答:使用钩子,在某个生命周期的时候使用一个函数
new Vue({
data:{
n:0
},
created(){
//当这个实例被创建的时候,就去监听n
this.$watch('n',function(){
console.log('n 变了')
},{immediate:true})
}
})