面试题:Vue 中的 watch 怎么深度监听对象变化?

在 Vue 中,watch 用于监听响应式数据的变化。默认情况下,watch 是浅层监听的,即只能监听对象引用的变化,而不会监听对象内部属性的变化。如果需要深度监听对象内部属性的变化,可以通过以下方式实现:


1. 使用 deep 选项

watch 的配置对象中,设置 deep: true,可以深度监听对象内部属性的变化。

示例:

export default {
data() {
return {
user: {
name: 'Alice',
age: 25,
},
};
},
watch: {
user: {
handler(newVal, oldVal) {
console.log('user 对象发生变化:', newVal);
},
deep: true, // 深度监听
},
},
};
export default {
  data() {
    return {
      user: {
        name: 'Alice',
        age: 25,
      },
    };
  },
  watch: {
    user: {
      handler(newVal, oldVal) {
        console.log('user 对象发生变化:', newVal);
      },
      deep: true, // 深度监听
    },
  },
};
export default { data() { return { user: { name: 'Alice', age: 25, }, }; }, watch: { user: { handler(newVal, oldVal) { console.log('user 对象发生变化:', newVal); }, deep: true, // 深度监听 }, }, };

说明:

  • deep: true 会递归监听对象的所有属性变化。
  • 注意:newValoldVal 的值是相同的,因为它们是同一个对象的引用。

2. 监听对象的特定属性

如果只需要监听对象的某个特定属性,可以直接监听该属性。

示例:

export default {
data() {
return {
user: {
name: 'Alice',
age: 25,
},
};
},
watch: {
'user.name'(newVal, oldVal) {
console.log('user.name 发生变化:', newVal, oldVal);
},
},
};
export default {
  data() {
    return {
      user: {
        name: 'Alice',
        age: 25,
      },
    };
  },
  watch: {
    'user.name'(newVal, oldVal) {
      console.log('user.name 发生变化:', newVal, oldVal);
    },
  },
};
export default { data() { return { user: { name: 'Alice', age: 25, }, }; }, watch: { 'user.name'(newVal, oldVal) { console.log('user.name 发生变化:', newVal, oldVal); }, }, };

说明:

  • 通过字符串路径(如 'user.name')可以监听对象的特定属性。
  • 这种方式比 deep: true 更高效,因为它只监听特定属性。

3. 使用 $watch 方法

在组件实例中,可以使用 $watch 方法动态添加监听器,并设置 deep: true

示例:

export default {
data() {
return {
user: {
name: 'Alice',
age: 25,
},
};
},
created() {
this.$watch(
'user',
(newVal, oldVal) => {
console.log('user 对象发生变化:', newVal);
},
{ deep: true } // 深度监听
);
},
};
export default {
  data() {
    return {
      user: {
        name: 'Alice',
        age: 25,
      },
    };
  },
  created() {
    this.$watch(
      'user',
      (newVal, oldVal) => {
        console.log('user 对象发生变化:', newVal);
      },
      { deep: true } // 深度监听
    );
  },
};
export default { data() { return { user: { name: 'Alice', age: 25, }, }; }, created() { this.$watch( 'user', (newVal, oldVal) => { console.log('user 对象发生变化:', newVal); }, { deep: true } // 深度监听 ); }, };

说明:

  • $watch 方法可以在组件生命周期中动态添加监听器。
  • 适合需要根据条件动态监听数据的场景。

4. 使用 watchEffect(Vue 3)

在 Vue 3 中,可以使用 watchEffect 自动追踪响应式数据的变化,并支持深度监听。

示例:

import { ref, watchEffect } from 'vue';
export default {
setup() {
const user = ref({
name: 'Alice',
age: 25,
});
watchEffect(() => {
console.log('user 对象发生变化:', user.value);
});
return {
user,
};
},
};
import { ref, watchEffect } from 'vue';

export default {
  setup() {
    const user = ref({
      name: 'Alice',
      age: 25,
    });

    watchEffect(() => {
      console.log('user 对象发生变化:', user.value);
    });

    return {
      user,
    };
  },
};
import { ref, watchEffect } from 'vue'; export default { setup() { const user = ref({ name: 'Alice', age: 25, }); watchEffect(() => { console.log('user 对象发生变化:', user.value); }); return { user, }; }, };

说明:

  • watchEffect 会自动追踪回调函数中使用的响应式数据。
  • 如果需要深度监听对象,可以直接访问对象的属性。

5. 注意事项

  • 性能开销:深度监听会递归遍历对象的所有属性,可能会带来性能开销,尤其是在监听大型对象时。
  • 避免无限循环:如果在监听器中修改了被监听的对象,可能会导致无限循环。

示例:

watch: {
user: {
handler(newVal, oldVal) {
this.user.name = 'Bob'; // 修改被监听的对象,可能导致无限循环
},
deep: true,
},
},
watch: {
  user: {
    handler(newVal, oldVal) {
      this.user.name = 'Bob'; // 修改被监听的对象,可能导致无限循环
    },
    deep: true,
  },
},
watch: { user: { handler(newVal, oldVal) { this.user.name = 'Bob'; // 修改被监听的对象,可能导致无限循环 }, deep: true, }, },

总结

在 Vue 中深度监听对象变化的方式包括:

  1. 使用 deep: true 选项:递归监听对象的所有属性。
  2. 监听对象的特定属性:通过字符串路径监听特定属性。
  3. 使用 $watch 方法:动态添加深度监听器。
  4. 使用 watchEffect(Vue 3):自动追踪响应式数据的变化。

根据具体需求选择合适的方式,可以高效地监听对象的变化并避免性能问题。

THE END
点赞8 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容