1.6 vue 监听

#王者杯·14天创作挑战营·第4期#

在 Vue 2 中,watch 是一个非常有用的功能,它允许你监听数据的变化,并在数据发生变化时执行相应的逻辑。这对于需要在数据更新时触发复杂操作(比如异步请求、依赖多个状态的计算等)特别有用。

基本使用

你可以直接在组件的 watch 选项中定义监听器来监听某个属性的变化:

new Vue({
  el: '#demo',
  data() {
    return {
      message: 'Hello Vue!'
    }
  },
  watch: {
    message(newValue, oldValue) {
      console.log('newValue:', newValue);
      console.log('oldValue:', oldValue);
    }
  }
});

在这个例子中,每当 message 发生变化时,都会触发这个监听器,并打印新旧值。

监听对象的某个深层属性

 方法1:使用函数作为监听器(推荐)

这是最常用和最直接的方法。将 watch 的键设置为一个函数,该函数返回你想要监听的深层属性的值。

new Vue({
  el: '#app',
  data() {
    return {
      user: {
        name: 'John Doe',
        age: 30
      }
    };
  },
  watch: {
    // ✅ 正确:使用函数返回要监听的值
    'user.name'(newVal, oldVal) {
      console.log(`Name changed from "${oldVal}" to "${newVal}"`);
    }
    // 或者写成函数形式(等效)

    //() => this.user.name: function(newVal, oldVal) {
    //  console.log(`Name changed from "${oldVal}" to "${newVal}"`);
    //}

  }
});

  • 注意:Vue 2 的 watch 确实支持使用 'user.name' 这种字符串路径作为键,但这是一种特殊的语法糖,它内部会将其转换为一个访问路径的函数。虽然这种写法在实践中被广泛使用且有效,但严格来说,它依赖于 Vue 的内部实现。

方法 2:计算属性 (computed) + watch

创建一个计算属性来提取你关心的深层属性,然后监听这个计算属性。

new Vue({
  el: '#app',
  data() {
    return {
      user: {
        name: 'John Doe',
        age: 30
      }
    };
  },
  computed: {
    // ✅ 计算属性返回 user.name
    userName() {
      return this.user.name;
    }
  },
  watch: {
    // ✅ 监听计算属性
    userName(newVal, oldVal) {
      console.log(`Name changed from "${oldVal}" to "${newVal}"`);
    }
  }
});

优点:逻辑清晰,性能好(只在 user.name 真正变化时触发)。 缺点:代码稍显冗余,需要额外定义一个计算属性。


总结

  • 直接在 watch 选项中使用 'user.name' 字符串路径,期望 Vue 自动解析,这种理解是不准确的。虽然 Vue 2 实现了这种语法糖,但它不是通过查找名为 user.name 的属性实现的。
  • 正确理解:Vue 2 的 watch 通过函数特殊的路径解析机制来监听深层属性。
  • 推荐方法
    1. 函数方式() => this.user.name (最清晰)。
    2. 计算属性方式:结合 computed 使用,逻辑分离,性能好。
    3. 深度监听:当需要监听对象多个属性时使用。

深度监听

如果你需要监听一个对象内部的变化,可以使用 deep: true 来启用深度监听:

new Vue({
  el: '#demo',
  data() {
    return {
      userProfile: {
        name: 'John Doe',
        age: 30
      }
    }
  },
  watch: {
    userProfile: {
      handler(newValue, oldValue) {
        console.log('userProfile changed');
      },
      deep: true
    }
  }
});

注意,由于 JavaScript 对象引用的问题,在深度监听回调函数中,newValueoldValue 可能会指向同一个对象。

立即执行

有时候你可能希望在监听开始的时候立即执行一次监听器函数,这时可以使用 immediate: true 选项:

new Vue({
  el: '#demo',
  data() {
    return {
      question: ''
    }
  },
  watch: {
    question: {
      handler(newQuestion) {
        console.log('question changed:', newQuestion);
      },
      immediate: true
    }
  }
});

这会在监听器被创建时立即执行一次。

监听多个来源

你也可以在一个监听器里同时监听多个数据源:

new Vue({
  el: '#demo',
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  watch: {
    firstName(newVal) {
      this.fullName = newVal + ' ' + this.lastName;
    },
    lastName(newVal) {
      this.fullName = this.firstName + ' ' + newVal;
    }
  }
});

或者,如果你想在一个监听器内处理多个数据源,可以通过监听一个计算属性的方式来实现:

new Vue({
  el: '#demo',
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe'
    }
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName;
    }
  },
  watch: {
    fullName: function() {
      console.log('fullName has changed');
    }
  }
});

使用 $watch 方法

除了在组件选项中定义监听器外,Vue 还提供了一个实例方法 $watch,可以在组件生命周期内的任何时刻动态地添加监听器:

this.$watch('message', function(newValue, oldValue) {
  console.log(newValue, oldValue);
});

$watch 返回一个取消监听的函数,调用它可以停止监听:

var unwatch = this.$watch('message', function() { /* ... */ });
// 之后取消监听
unwatch();

$watchwatch 选项在 Vue.js 中都用于监听数据的变化,但它们的使用场景和一些特性有所不同。

$watch 方法

  • 动态添加监听器$watch 是一个实例方法,允许你在组件创建后的任何时间点动态地添加监听器。这为开发者提供了更大的灵活性,尤其是在需要根据运行时条件来决定是否监听某些数据变化的情况下。

  • 返回值:调用 $watch 方法会返回一个取消监听的函数。你可以调用这个函数来停止监听。这对于需要手动管理监听器生命周期的情况特别有用。

    // 动态添加监听器
    var unwatch = this.$watch('someData', function (newVal, oldVal) {
      console.log('someData changed from', oldVal, 'to', newVal);
    });
    
    // 在适当的时候停止监听
    unwatch();
  • 立即执行:与 watch 选项不同,$watch 默认不会在监听开始时立即执行一次监听回调(除非你设置了 immediate: true)。如果你希望在监听开始时也执行回调,可以传递第三个参数 { immediate: true }$watch

watch 选项

  • 静态定义监听器watch 是 Vue 组件的一个选项,允许你在组件初始化时静态地定义监听器。这种方式更适合于那些在组件整个生命周期内都需要监听的数据变化。

    new Vue({
      el: '#demo',
      data() {
        return {
          message: 'Hello Vue!'
        }
      },
      watch: {
        message(newVal, oldVal) {
          console.log('message changed from', oldVal, 'to', newVal);
        }
      }
    });
  • 配置更灵活:通过 watch 选项定义的监听器可以接受更多配置项,比如 deep(深度监听)和 immediate(立即执行)。这意味着你可以更容易地设置监听器的行为,而不需要额外的逻辑。

    new Vue({
      el: '#demo',
      data() {
        return {
          userProfile: {
            name: 'John Doe',
            age: 30
          }
        }
      },
      watch: {
        userProfile: {
          handler(newVal, oldVal) {
            console.log('userProfile changed');
          },
          deep: true,
          immediate: true
        }
      }
    });

总结

  • 使用 watch 选项适合在组件初始化时静态定义监听器,并且当你可能需要利用其丰富的配置选项(如深度监听、立即执行等)时。

  • 使用 $watch 方法则更适合在运行时动态添加或移除监听器,尤其是当你需要控制监听器的生命周期或者基于某些条件来决定是否监听某个数据源时。

两者各有优势,选择哪一个取决于你的具体需求和应用场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值