在 Vue 开发中,watch
是一个非常强大的工具,用于监听数据变化并执行相应的操作。它适用于那些需要在数据发生变化时执行异步或复杂操作的场景。本文将详细介绍 Vue2 中 watch
的使用方式、配置项以及其与 Vue3 的差异 ,同时还会对比 watch
和 computed
的区别与适用场景。
🧩 一、Vue2 中 watch
的基本用法
1. 简单监听
javascript
export default {
data() {
return {
message: 'Hello Vue'
};
},
watch: {
message(newVal, oldVal) {
console.log('message changed:', newVal, oldVal);
}
}
};
当 message
值发生变化时,回调函数会被触发,输出新旧值。
2. 使用对象形式(添加配置项)
Vue2 支持以对象形式定义 watch
,从而可以使用更多高级功能:
javascript
watch: {
message: {
handler(newVal, oldVal) {
console.log('message changed:', newVal, oldVal);
},
immediate: true, // 页面初始化时也触发一次
deep: false // 是否深度监听
}
}
handler
: 回调函数,接收新值和旧值。immediate
: 若为true
,页面加载时立即执行一次回调。deep
: 若为true
,会深度监听对象内部属性的变化(适用于对象或数组)。
3. 监听对象中的某个属性(字符串路径)
javascript
data() {
return {
user: {
name: 'Tom',
age: 20
}
};
},
watch: {
'user.name': {
handler(newVal, oldVal) {
console.log('user.name changed:', newVal);
},
immediate: true
}
}
这种方式适合监听嵌套对象的某个具体属性。
4. 深度监听对象
如果你希望监听整个对象的变化(包括对象内部任意属性),可以设置 deep: true
:
javascript
watch: {
user: {
handler(newVal) {
console.log('user object changed', newVal);
},
deep: true
}
}
⚠️ 注意:深度监听可能会带来性能开销,特别是对象较大或频繁更新时。
🔄 二、Vue3 中 watch
的写法与对比
Vue3 中的响应式系统进行了重构(基于 Proxy),因此 watch
的语法也有一定变化。主要体现在:
- 在 Vue3 中,
watch
不再是选项式 API 中的一个单独配置项,而是通过 Composition API 来使用。 - 更加灵活,支持监听多个源、组合逻辑等。
1. Vue3 Composition API 中的 watch
基本用法:
javascript
import { ref, watch } from 'vue';
export default {
setup() {
const count = ref(0);
watch(count, (newVal, oldVal) => {
console.log('count changed:', newVal, oldVal);
});
return { count };
}
};
监听响应式对象的某个属性:
javascript
const user = reactive({ name: 'Tom' });
watch(
() => user.name,
(newVal) => {
console.log('user.name changed:', newVal);
}
);
同时监听多个值:
javascript
watch([() => firstName.value, () => lastName.value], ([newFirst, newLast]) => {
console.log('Name changed:', newFirst, newLast);
});
设置 immediate
和 deep
javascript
watch(
() => user,
(newVal) => {
console.log('user changed:', newVal);
},
{ deep: true, immediate: true }
);
✅ Vue2 与 Vue3 watch
对比总结
特性 | Vue2 | Vue3 |
---|---|---|
写法 | 选项式 API | Composition API |
监听对象属性 | 字符串路径 'obj.key' |
使用 () => obj.key |
多值监听 | 不支持原生,需封装 | 原生支持数组形式 |
配置项 | immediate 、deep |
同样支持,作为第三个参数传入 |
性能 | 可控但略显笨重 | 更加灵活、模块化 |
🔁 三、watch
与 computed
的区别与使用建议
1. computed
------ 依赖缓存,返回值
- 用途:用于根据已有响应式数据计算出新的值。
- 特点 :
- 基于它的响应式依赖进行缓存。
- 如果依赖的数据没有变化,多次访问会直接返回缓存结果。
- 示例:
javascript
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
2. watch
------ 异步/副作用处理
- 用途:执行异步操作或复杂的副作用逻辑(如请求接口、修改 DOM 等)。
- 特点 :
- 没有返回值。
- 适合处理状态变化后的一系列行为。
- 示例:
javascript
watch: {
searchQuery(newVal) {
if (newVal) {
this.fetchResults();
}
}
}
✅ 对比总结
特性 | computed |
watch |
---|---|---|
是否有返回值 | 有 | 无 |
是否缓存 | 是 | 否 |
是否异步友好 | 否(不推荐) | 是 |
是否适合副作用 | 否 | 是 |
是否自动追踪依赖 | 是 | 是 |
典型用途 | 数据转换、格式化 | 异步请求、事件触发、状态同步 |
📌 四、最佳实践与注意事项
✅ 推荐使用原则:
- 如果你需要从已有数据派生出新数据,并且这个新数据会被模板使用,优先使用
computed
。 - 如果你希望在数据变化时执行一些副作用(比如网络请求、定时器、DOM 操作等),请使用
watch
。 - 在 Vue3 中,推荐使用 Composition API 提供的
watch
和computed
,结构更清晰、逻辑可复用性强。
❗ 常见问题与解决办法:
1. watch
中无法获取最新值?
- 确保你监听的是响应式数据(
ref
/reactive
)。 - 对象类型记得使用
deep: true
或者监听特定属性。
2. watch
初始化时不触发?
- 添加
immediate: true
即可。
3. watch
执行频率过高?
- 使用
debounce
节流处理,尤其是在监听输入框内容变化时。
🧠 五、进阶技巧
1. 使用 nextTick()
延迟执行
javascript
this.$nextTick(() => {
this.fetchData();
});
在 watch
中执行 DOM 操作前,确保 DOM 已更新。
2. 封装可复用的 Watcher 函数
在 Vue3 中可以将 watch
封装成自定义 Hook,提高代码复用性:
javascript
function useWatchSearch(fetchResults) {
const searchQuery = ref('');
watch(searchQuery, (newVal) => {
if (newVal) fetchResults();
});
return { searchQuery };
}
📚 六、结语
无论是 Vue2 还是 Vue3,watch
都是一个不可或缺的响应式工具。它让我们能够优雅地处理数据变化带来的副作用。而 computed
则更适合用于数据的衍生计算。
掌握它们之间的区别与适用场景,可以帮助我们写出更高效、更易维护的 Vue 应用。
📖 参考文档
如果你喜欢这篇文章,欢迎关注我的博客,后续将持续分享 Vue、React、前端工程化等干货内容!