侦听属性,响应数据(data&computed)的变化,当数据变化时,会立刻执行对应函数,
虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

值类型

函数类型

例:

  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. msg: 'hello,你好呀,我是杉杉',
  5. },
  6. watch: {
  7. msg () {
  8. console.log('msg的值改变啦~');
  9. }
  10. }
  11. })
  12. // 更改msg的值
  13. vm.msg = 'hello~~~~'; // 此时会在控制台中打印出` msg的值改变啦 `

侦听器函数,会接收两个参数,第一个参数为newVal(被改变的数据),第二个参数为oldVal(赋值新值之前的值)。如在上述代码中,将侦听器watch更改一下,如:

  1. watch: {
  2. msg (newVal,oldVal) {
  3. conosle.log(newVal, oldVal);
  4. }
  5. }
  6. // 更改msg的值
  7. vm.msg = 'hello~~~~'; // 此时会在控制台中打印出`hello,你好呀,我是杉杉 hello~~~~`

字符串类型

值为方法名字,被侦听的数据改变时,会执行该方法。

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. msg: '杉杉'
  5. },
  6. watch: {
  7. msg: 'msgChange'
  8. },
  9. methods: {
  10. msgChange () {
  11. console.log('msg的值改变啦');
  12. }
  13. }
  14. })
  15. vm.msg = 'hello'; // 此时msgChange函数会执行,控制台中打印出 ` msg的值改变啦 `

对象类型

写成对象类型时,可以提供选项。

handler—被侦听的数据改变时执行的回调函数

必需。handler时被侦听的数据改变时执行的回调函数。
handler的值类型为函数/字符串,写成字符串时为一个方法的名字。

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. msg: '杉杉'
  5. },
  6. watch: {
  7. msg: {
  8. handler () {
  9. console.log('msg的值改变啦');
  10. }
  11. }
  12. }
  13. })
  14. vm.msg = 'hello'; // 此时回调函数会执行,控制台中打印出 ` msg的值改变啦 `

deep—无论该对象被嵌套的有多深,都会被侦听到

在默认情况下,侦听器侦听对象只侦听引用的变化,只有在给对象赋值时它才能被监听到。所以需要使用deep选项,让其可以发现对象内部值的变化,将deep的值设置为true,那么无论该对象被嵌套的有多深,都会被侦听到。

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. personObj: {
  5. name: '邓旭明',
  6. age: 88
  7. }
  8. },
  9. watch: {
  10. personObj: {
  11. handler () {
  12. console.log('对象的值改变啦');
  13. },
  14. deep: true // 开启深度侦听
  15. }
  16. }
  17. })
  18. vm.obj.name = '老邓头'; // 此时回调函数会执行,控制台中打印出 ` 对象的值改变啦 `

注意,当对象的属性较多的时候,性能开销会比较大,此时可以监听对象的某个属性,这个后面再说。

immediate—侦听开始之后立刻被调用

加上immediate选项后,回调将会在侦听开始之后立刻被调用。而不是等待侦听的数据更改后才会调用。

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. msg: '杉杉'
  5. },
  6. watch: {
  7. msg: {
  8. handler () {
  9. console.log('回调函数执行啦');
  10. },
  11. immediate: true
  12. }
  13. }
  14. })
  15. // 此时未更改msg的值,就会在控制台打印出来` 回调函数执行啦 `

数组类型

可以将多种不同值类型写在一个数组中。如:

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. msg: '杉杉'
  5. },
  6. watch: {
  7. msg: [
  8. 'msgChange',
  9. function () {},
  10. {
  11. handler () {},
  12. deep: true,
  13. immediate: true
  14. }
  15. ]
  16. }
  17. })

键类型

正常对象key值

以上演示的都是正常的对象key值,这里不再赘述。

字符串类型key值

当key值类型为字符串时,可以实现监听对象当中的某一个属性,如:

  1. const vm = new Vue({
  2. el: '#app'
  3. data: {
  4. personObj: {
  5. name: '邓旭明',
  6. age: 88
  7. }
  8. },
  9. watch: {
  10. 'personObj.name' () {
  11. console.log('对象的值改变啦');
  12. }
  13. }
  14. })
  15. vm.obj.name = '老邓头'; // 此时回调函数会执行,控制台中打印出 ` 对象的值改变啦 `

vm.$watch

Vue实例将会在实例化时调用$watch,遍历watch对象的每一个属性。
我们也可以利用vm.$watch来实现侦听,用法与watch选项部分一致,略有不同。以下为使用方法。

  1. 侦听某个数据的变化
  1. // 1. 三个参数,一参为被侦听的数据;二参为数据改变时执行的回调函数;三参可选,为设置的选项对象
  2. vm.$watch(
  3. 'msg',
  4. function () {
  5. // 干了点事儿
  6. },
  7. {
  8. deep: Boolean,
  9. immediate: Boolean
  10. }
  11. )
  12. // 2. 二个参数,一参为被侦听的数据;二参为选项对象,其中handler属性为必需,是数据改变时执行的回调函数,其他属性可选。
  13. vm.$watch(
  14. 'msg',
  15. {
  16. handler () {
  17. // 干了点事儿
  18. },
  19. deep: Boolean,
  20. immediate: Boolean
  21. }
  22. )
  1. 侦听某个对象属性的变化
  1. vm.$watch('obj.name', /**参数和上面一之*/)
  1. 当监听的数据的在初始不确定,由多个数据得到时,此时可以将第一个参数写成函数类型
  1. const vm = new Vue({
  2. el: '#app',
  3. data: {
  4. num1:10,
  5. num2:20,
  6. },
  7. computed:{
  8. sum(){
  9. return this.num1 + this.num2;
  10. }
  11. },
  12. })
  13. const unwatch = vm.$watch(
  14. 'sum',
  15. function(){
  16. console.log('sum 改变啦')
  17. unwatch()
  18. }
  19. )

侦听器函数执行后,会返回一个取消侦听函数,用来停止触发回调:

  1. const unwatch = vm.$watch('msg', function () {});
  2. unwatch(); // 执行后会取消侦听msg数据

使用unwatch时,需要注意的是,在带有immediate选项时,不能在第一次回调时取消侦听数据。

  1. const unwatch = vm.$watch('msg', function () {
  2. // 干了点儿事
  3. unwatch(); // 此时会报错
  4. },{
  5. immediate: true
  6. }
  7. })

如果仍然希望在回调内部用一个取消侦听的函数,那么可以先检查该函数的可用性:

  1. var unwatch = vm.$watch('msg', function () {
  2. // 干了点儿事
  3. if(unwatch) {
  4. unwatch();
  5. }
  6. },{
  7. immediate: true
  8. }
  9. })

侦听器 vs 计算属性

  1. 两者都可以观察和响应Vue实例上的数据的变动。
  2. watch擅长处理的场景是:一个数据影响多个数据。计算属性擅长处理的场景是:多个数据影响一个数据。
  3. 在侦听器中可以执行异步,但是在计算属性中不可以,例:

使用侦听器:

  1. var vm = new Vue({
  2. el: '#app',
  3. data: {
  4. question: '',
  5. },
  6. watch: {
  7. question () {
  8. setTimeout(() => {
  9. alert(this.question);
  10. }, 1000)
  11. }
  12. }
  13. })