从0开始学Vue系列5--监视属性

130 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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)
                }
            }
        } 
    })

图片5.png

解析:这里实现的是个点击切换天气按钮就实现两个文字之间的转换,changeWeather方法在methods里面被定义,实现isHot属性值的切换,info计算属性在computed里被定义实现文字的切换。

要实现监视,就要使用watch配置,我们这里监视的是在data里定义的isHot属性,handler函数里面有两个参数,字面意思可以看出是旧的值和新的值,handler函数当被监视的属性(这里是isHot)发生改变时就会被调用,常见的场景有检测到属性的变化后做对比+行动等。

3. 配置项分析:

  • immediate:true 配置项的作用是初始化时就让handler被调用,不用等到监视属性变化,它的默认值为`false
  • deep: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回调函数等等),最好要写成箭头函数形式,这样我们才可以使用我们定义好的的属性。