Vue2基础 06:监视属性/侦听器

前一节讲到计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。

此时计算属性就不再适用,Vue给我们提供了监视属性/侦听器

1 介绍

定义 被侦听的属性,在被赋新值时,会触发回调函数handler。

  1. 当被监视的属性变化时,回调函数handler自动调用
  2. 监视属性必须存在,才能进行监视

一般写法

 watch:{
      被监听的属性:{
           immediate:true, //初始化时让handler调用一下
           handler(newValue,oldValue){
               //逻辑
           }//当该属性发生改变时调用
      }
}

一开始并不会自动调用监视属性里对应的handler函数,可以加上immediate:true让handler调用

案例
上面一行显示的天气信息,用插值语法绑定计算属性info;下面是一个绑定了methods的按钮,点击后会调用methods里的changeWeather函数;点击按钮,会对天气信息进行更改。

画面
在这里插入图片描述
在这里插入图片描述

实现代码

<body>
    <div id="root">
        <h2>今天的天气{{info}}</h2>
        <button @click="changeWeather">切换</button>
    </div>
</body>

<script type="text/javascript" src="../vue.js">
    new Vue({
        el:'#root',  
        data:{ 
            isHot:true
        },
        computed:{
            info(){
                return this.isHot ? '炎热' : '凉爽'
                //此处为三元表达式
            }
        },
        methods:{
            changeWeather(){
                this.isHot = !this.isHot
            }
        }
        
        watch:{
            isHot:{
                immediate:true, //初始化时让handler调用一下
                handler(newValue,oldValue){
                    console.log(this.isHot,'isHot')
                }//当isHot发生改变时调用
            },//监视data属性
            info:{
                immediate:true, //初始化时让handler调用一下
                handler(newValue,oldValue){
                    console.log(this.info,'info')
                }//当isHot发生改变时调用
            }//监视计算属性
        }
    })  
</script>

三元表达式的补充

点击切换按钮后,调用了绑定的changeWeather函数,改变了dataisHot的值,然后发生以下的影响:

  • 监视到isHot值发生改变,于是调用了对应handler函数
  • 计算属性info根据三元表达式返回对应值
  • 监视到info发生改变,于是调用了对应handler函数
    在这里插入图片描述

第二种写法
若已经创建好Vue实例,需要新增监视,则可以采用以下这种写法。

    vm.$watch('isHot',{
        immediate:true, //初始化时让handler调用一下
        handler(newValue,oldValue){
            console.log(this.isHot,'isHot')
        }
    })

关于采用哪种监视方法:
(1)在创建实例时,已经清楚要监视谁,就用第一种
(2)反则,需要后续根据用户行为才需要监视,就用第二种

小改写
将按钮绑定的事件不写在methods中,可以直接写在绑定事件里。

<button @click="isHot = !isHot">切换</button>

绑定事件时候:@xxx="yyy" 可以写简单的语句,但是不推荐用间隔写多个语句

2 深度监视

Vue自身可以检测对象内部值的改变,但Vue中的watch默认不检测对象内部值的改变(默认看一层)。

案例
在data中定义一个对象numbers,有两个属性以及给定的属性值;点击按钮后,numbers中的属性a值+1。
在这里插入图片描述

定义
监视多级结构中某个属性的变化,这里是要监视numbers中的a是否变化

代码

<body>
    <div id="root"> 
        <h3>a的值是:{{numbers.a}}</h3>
        <button @click="numbers.a++">点我a+1</button>
    </div>
</body>

<script type="text/javascript" src="../vue.js">
    new Vue({
        el:'#root',  
        data:{ 
            numbers:{
                a:1,
                b:1
            }
        },
        watch:{
            //监视多级结构中某个属性的变化
            'numbers.a':{
                 handler(newValue,oldValue){
                    console.log('a被改变了')
                }
            }
            numbers:{
                handler(){
                  console.log('numbers改变了')
                }
            }
        }
    })
</script>

此时点a+1按钮无反应,无法监视numbers{}里的东西改变,因为其保存的是对象的地址.

监视的对象不能写为numbers.a,因为JS中对象的key(即data的numbers)永远是字符串,所以这里要写原始写法

写法
配置deep:true可以检测对象内部值该改变(多层),根据具体结构决定是否开启

numbers:{
     deep:true,//默认为false
     handler(){
           onsole.log('numbers改变了')
     }
}

3 监视的简写形式

前提:配置项只有handler

3.1 在vue里简写

一般:

 watch:{
     isHot:{
     handler(newValue,oldValue){
           onsole.log('isHot被修改了',newValue,oldValue)
     }
}

简写:

 watch:{
     isHot(newValue,oldValue){
        onsole.log('isHot被修改了',newValue,oldValue)
     }
}

3.2 在vue外简写

一般

vm.$watch('isHot',{
    immediate:true, 
     <!--初始化时让handler调用一下-->
    deep:true,<!--默认为false-->
    handler(newValue,oldValue){
        console.log()
    }
})

简写

vm.$watch('isHot',funtion(newValue,oldValue){
    console.log('isHot被修改了',newValue,oldValue)
})

4 计算属性computed与监视属性watch的区别

  • 计算属性能完成的,监视属性都可以完成,优先考虑计算属性
  • 监视属性能完成的,计算属性不一定能完成,例如:watch可以进行异步操作

案例
两个输入框分别展示姓和名,然后自动拼成全名,采用定时器延迟一秒显示改变。

有关定时器

  1. 定时器是在vue管理的函数firstname中开启的,但是其所指定的回调是不受Vue控制的,而是由浏览器定时器管理模块控制的,定时器到点了是JS引擎调的,这种地方需要写成箭头函数。
  2. 定时器内若写成了普通函数,控制台打印出的this也是window

尝试用计算属性实现

<body>
    <div id="root">
        姓:<input type="text" v-model="firstname" > <br/><br/>
        名:<input type="text" v-model="lastname" ><br/><br/>
        全名:<span>{{fulName}}</span>
    </div>
</body>

<script type="text/javascript" src="../vue.js">
    new Vue({
        el:'#root',  
        data:{ 
            firstname:'张',
            lastname:'三',
        },
        
        //计算属性
        computed:{
            fulname(val){
                setTimeout(() => {
                    this.fulName = val + '-' + this.lastname
                },1000)
            }//函数直接当getter()用
            lastname(val){
                this.fulName = this.firstname + '-' + val
            }
        }
    })
</script>

此时在计算属性的{}里加函数,return的返回值给不到此属性。

监视属性实现

<body>
    <div id="root">
        姓:<input type="text" v-model="firstname" > <br/><br/>
        名:<input type="text" v-model="lastname" ><br/><br/>
        全名:<span>{{fulName}}</span>
    </div>
</body>

<script type="text/javascript" src="../vue.js">
    new Vue({
        el:'#root',  
        data:{ 
            firstname:'张',
            lastname:'三',
            fulName:'张-三'
        },

        //监视属性
        watch:{
            firstname(val){
                setTimeout(() => {
                    this.fulName = val + '-' + this.lastname
                },1000)
            },
            lastname(val){
                this.fulName = this.firstname + '-' + val
            }
        }
    })
</script>

箭头函数和普通函数:

  1. 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vue实例或组件实例对象
  2. 所有不被vue管理的函数(定时器的回调函数、Ajax的回调函数、Promise的回调函数)最好写成箭头函数,这样this的指向才是Vue实例或组件实例对象
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值