Vue——watch选项详解

1. 什么是watch选项?(官方解释)
  • 类型:{ [key: string]: string | Function | Object | Array }
  • 详细:一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例i化时调用 $watch(),遍历 watch 对象的每一个属性。
2. 通俗解释
  • watch选项能够监听值的变化。
3. 简单使用
<div>
      <p>Number: {{ myNumber }}</p>
      <p>Number: <input type="text" v-model.number="myNumber"></p>
</div>
 
new Vue({
  el: '#root',
  data: {
    myNumber: 'Dawei'
  },
  watch: {
    myNumber(newVal, oldVal) {
      console.log('newVal', newVal);
      console.log('oldVal', oldVal);
    }
  } 
})

根据上面的代码,在输入框输入内容,控制台会显示新值还有旧值。

4. handler方法和immediate属性

根据上面的例子我们加以改造

<div>
      <p>Number: {{ myNumber }}</p>
      <p>Number: <input type="text" v-model.number="myNumber"></p>
</div>
 
new Vue({
  el: '#root',
  data: {
    myNumber: 'Dawei'
  },
  watch: {
        myNumber: {
            handler(newVal, oldVal) {
                console.log('newVal', newVal);
                console.log('oldVal', oldVal);
            },
            immediate: true
        }
    } 
})
  • handler方法就是你watch中需要具体执行的方法;
  • immediate为true时则立即触发回调函数;如果为false,则和上面的例子一样,不会立即执行回调。
5. deep属性

上面两个例子都是监听简单数据类型的数据,对于对象或者对象中的属性,我们如何监听?那么就介绍deep属性。它的作用就是解决这个问题的关键。

<div>
      <p>Obj-a: {{ obj.a }}</p>
      <p>Obj-a: <input type="text" v-model="obj.a"></p>
</div>

new Vue({
  el: '#root',
  data: {
    obj: {
        a: ''
    }
  },
  watch: {
        'obj': {
            handler(newVal, oldVal) {
                console.log('newVal-obj.a', obj.a);
                console.log('oldVal-obj.b', obj.a);
            },
            deep: true
        }
    } 
})

deep顾名思义就是深入监听,也就是在对象中层层遍历,并在监听对象上的每一个属性上都添加监听,固然也会损耗性能。

6. 注销监听

在第五点后面我提到了损耗性能,但对于组件开发的情况下是不存在,监听事件会随着组件的销毁而销毁。而在组件外声明的监听事件,我们需要使用unWatch方法注销,防止内存溢出。

7. 监听的多种写法(只介绍常用的两种)
// 第一种
<div>
      <p>Obj-a: {{ obj.a }}</p>
      <p>Obj-a: <input type="text" v-model="obj.a"></p>
</div>

new Vue({
  el: '#root',
  data: {
    obj: {
        a: ''
    }
  },
  watch: {
        obj: { // <--重点看这里
            handler(newVal, oldVal) {
                console.log('newVal-obj.a', obj.a);
                console.log('oldVal-obj.b', obj.a);
            },
            deep: true
        }
    } 
})

// 第二种

<div>
      <p>Obj--a: {{ obj.a }}</p>
      <p>Obj--a: <input type="text" v-model="obj.a"></p>
</div>

new Vue({
  el: '#root',
  data: {
    obj: {
        a: ''
    }
  },
  watch: {
        'obj.a': { // <--重点看这里
            handler(newVal, oldVal) {
                console.log('newVal-obj.a', obj.a);
                console.log('oldVal-obj.b', obj.a);
            },
            deep: true
        }
    } 
})

8. 特别注意
  1. ES6中推出了箭头函数,上述例子我均未使用箭头函数,如果在handler函数中使用了箭头函数,改变了this指向,就无法获取到Vue实例,则为undifined。
  2. 对于父子组件传参,异步获取数据有时会存在获取不到值的情况。这时候watch就派上用场,适当的时候要配合immediate或者deep属性配合使用。
9. 源码解析
// state.js

function createWatcher (
  vm: Component,
  expOrFn: string | Function,
  handler: any,
  options?: Object
) {
  if (isPlainObject(handler)) {
    options = handler
    handler = handler.handler
  }
  if (typeof handler === 'string') {
    handler = vm[handler]
  }
  return vm.$watch(expOrFn, handler, options)
}

Vue的类初始化建立数据绑定时,会从用户传的参数来判断拿什么来做监听的数据变量,拿什么来当作监听到数据变更后的处理函数。因为在变量你传了一个对象,这个对象就是createWatcher函数参数中对应的handler,函数第一步逻辑就是判断它是不是一个对象,如果是对象,就拿它里面的handler参数来作为监听事件的处理函数。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值