Vue2-$watch监听器

595 阅读2分钟

Vue.js 中,$watch 是一个实例方法,用于监视 Vue 实例中数据的变化。它的返回值是一个取消监听的函数,直接调用该函数会停止触发回调。一旦取消监听,该数据的变化将不再触发 watch 的监听。$watch 接受三个参数:

  • 第一个参数:要监视的属性或表达式
  • 第二个参数:回调函数,当指定的属性发生变化时,回调函数将被调用
  • 第三个参数:配置参数immediatedeep
    • 若需要第一次运行就执行回调,可设置 { immediate: true }
    • 若需要深度监听对象的变化,可设置 { deep: true }

1# 监听基本类型:boolean、number、string

监听 booleannumberstring 类型的属性时,只需直接传入相应的变量名即可。若需要在初始化时立即执行监听,可设置 { immediate: true } 选项。

var vm = new Vue({
  data: {
    isActivated: false, // boolean 类型
    count: 0, // Number 类型
    message: 'Hello, Vue!', // string 类型
    name: 'lee', // string 类型
  },
  created: function() {
    // 监听 isActivated 属性的变化
    this.$watch('isActivated', function(newVal, oldVal) {
      console.log('isActivated 发生变化:', oldVal, ' => ', newVal);
    });

    // 监听 count 属性的变化
    this.$watch('count', function(newVal, oldVal) {
      console.log('count 发生变化:', oldVal, ' => ', newVal);
    });

    // 监听 message 属性的变化
    this.$watch('message', function(newVal, oldVal) {
      console.log('message 发生变化:', oldVal, ' => ', newVal);
    });

    // 监听 name 属性的变化,如果需要第一次就执行监听,可设置:{immediate: true}
    this.$watch('name', function(newVal, oldVal) {
      console.log('name 发生变化:', oldVal, ' => ', newVal);
    }, { immediate: true });
  },
  methods: {
    update: function() {
      // 更新 Boolean 类型数据
      this.isActivated = !this.isActivated;

      // 更新 Number 类型数据
      this.count++;
      
      // 更新 String 类型数据
      this.message = 'Hello, World!';
      this.name = 'leaf';
    }
  }
});

// 调用 update 方法更新数据
vm.update();

2# 监听对象:Object

监听对象类型的属性时,可通过设置 { deep: true } 监听对象所有属性的变化,也可通过直接传入对象属性路径(如 obj.xx )监听对象单个属性的变化。前者实现深度监测对象内部值的变化,包括嵌套对象的属性变化,后者则只监听特定属性的变化,不进行深度监测。

// 创建一个 Vue 实例
var vm = new Vue({
  data: {
    user: {
      name: 'lee',
      age: 23
    },
    point: {
      x: 0,
      y: 0
    }
  },
  created: function() {
    // 监听 point 对象
    this.$watch('point', function(newVal, oldVal) {
      console.log('point 对象变化:', oldVal, ' => ', newVal);
    });

    // 监听 user 对象的 name 属性
    this.$watch('user.name', function(newVal, oldVal) {
      console.log('姓名变化:', oldVal, ' => ', newVal);
    });

    // 监听 user 对象的 age 属性
    this.$watch('user.age', function(newVal, oldVal) {
      console.log('年龄变化:', oldVal, ' => ', newVal);
    });
  },
  methods: {
    update: function() {
      // 更新 user 对象的属性值
      this.user.name = 'leaf';
      this.user.age = 24;

      // 更新 point 对象的属性值
      this.point.x = 1;
      this.point.y = 1;
    }
  }
});

// 调用 update 方法更新数据
vm.update();

3# 监听数组:Array

监听一维或多维数组的属性时,无需深度监听,因为 Vue.js 默认可以捕捉数组的变化。但是,如果需要监测数组对象中的对象属性变化,就需要使用 { deep: true } 深度监听。这样可以确保无论对象属性变化发生在多少层内,都能被正确监测到。

// 创建一个 Vue 实例
new Vue({
  data: {
    // 包含一维数组
    flatArray: [1, 2, 3],
    
    // 包含二维数组
    nestedArray: [[1, 2], [3, 4]],
    
    // 包含对象的一维数组
    objectArray: [
      { name: 'Item 1', value: 10 },
      { name: 'Item 2', value: 20 }
    ]
  },
  created() {
    // 监听一维数组 flatArray 的变化
    this.$watch('flatArray', (newVal, oldVal) => {
      console.log('一维数组发生变化', newVal, oldVal);
    }, { deep: true });

    // 监听二维数组 nestedArray 的变化
    this.$watch('nestedArray', (newVal, oldVal) => {
      console.log('二维数组发生变化', newVal, oldVal);
    }, { deep: true });

    // 监听包含对象的一维数组 objectArray 的变化
    this.$watch('objectArray', (newVal, oldVal) => {
      console.log('包含对象的一维数组发生变化', newVal, oldVal);
    }, { deep: true });
  },
  methods: {
    update() {
      // 更新一维数组
      this.flatArray.push(4);

      // 更新二维数组
      this.nestedArray[0].push(5);

      // 更新包含对象的一维数组
      this.objectArray[0].value = 15;
    }
  }
});

// 调用 update 方法更新数据
vm.update();

注意$watch 监视数组的不足之处在于,它只能捕捉到数组本身的变化,例如数组长度的变化、元素的添加或删除,而无法深度监测数组内部元素的变化,特别是对数组中对象属性的修改,即如果对数组中的对象进行修改、添加或删除操作,$watch 是无法触发回调函数的;此外,对于大型数组或深度嵌套的数组,由于每次数组发生变化时,都会触发回调函数,使用 $watch 监视器可能会影响应用程序的响应性能。因此建议使用 $set 方法或侦听器来处理数组变化。