一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
我要一步一步往上爬~大家好,今天我们来一起学习一下监视属性这个概念,拿下Watch用法。
1. 定义:
对已有的属性进行监视,当被监视的属性变化时, 回调函数会自动被调用, 进行相关操作。
2. 案例解析:
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
immediate:true,
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
}
})
解析:这里实现的是个点击切换天气按钮就实现两个文字之间的转换,changeWeather方法在methods里面被定义,实现isHot属性值的切换,info计算属性在computed里被定义实现文字的切换。
要实现监视,就要使用watch配置,我们这里监视的是在data里定义的isHot属性,handler函数里面有两个参数,字面意思可以看出是旧的值和新的值,handler函数当被监视的属性(这里是isHot)发生改变时就会被调用,常见的场景有检测到属性的变化后做对比+行动等。
3. 配置项分析:
immediate:true配置项的作用是初始化时就让handler被调用,不用等到监视属性变化,它的默认值为`falsedeep:true
data:{
numbers:{
a:1,
b:1,
c:{
d:{
e:100
}
}
}
},
watch:{
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
}
深度监视,.Vue中的watch默认不监测对象(这里是numbers)内部值的改变,只会监视一层,也就是numbers本身,可以通过这个配置项监测对象内部值改变(多层)。
默认是关闭的,这是出于效率的考虑。
.Vue自身是可以通过下面这种形式去监测对象内部值的改变的,只是说Vue提供的watch默认不可以!
'numbers.a':{
handler(){
console.log('a被改变了')
}
4. 两种写法:
上面的代码中是一种写法,我们也可以简化写成下面这种形式,区别在于:
- 创建vm实例时就明确知道想要监视什么属性,就写上面那种
- 根据用户后续的行为决定监视什么属性的,就用这种
vm.$watch('isHot',{
immediate:true,
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
5. 简写形式:
当不需要其他很多配置项的时候,只需要响应handler时候就可以用简写,下面分别是两种写法的缩写形式:
isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
}
vm.$watch('isHot',function(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
})
6. computed 对比 watch:
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}</span> <br/><br/>
</div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
firstName:'小',
lastName:'李',
fullName:'小 李'
},
watch:{
firstName(newValue){
setTimeout(()=>{
console.log(this)
this.fullName = newValue + ' ' + this.lastName
},1000);
},
lastName(newValue){
this.fullName = this.firstName + '-' + newValue
}
}
})
</script>
区别:
computed能完成的功能watch都可以完成。而watch能完成的computed不一定能完成,例如这里setTimeout的延迟一秒修改需求的异步任务。
注意:
这里使用了箭头函数后,就没有自己的this了,它会往外找this,找到了firsname函数的this,这是被vue管理的函数,所以就可以使用fullname属性了,不使用箭头函数的话,这里的this是指windows,而windows上是没有fullname属性的,就会报错。
总结:
- 被
Vue管理的函数,最好写成普通函数,这样this指向的才是vm/组件实例对象 - 所有不被
Vue管理的函数(比如定时器回调函数、ajax回调函数等、Promise回调函数等等),最好要写成箭头函数形式,这样我们才可以使用我们定义好的的属性。