vue2和vue3的watch用法
在Vue 2和Vue 3中,watch
用于监听响应式数据的变化并执行副作用逻辑。两者核心功能一致,但Vue 3在组合式API中提供了更灵活的用法,并支持TypeScript类型推断。以下是详细对比和示例:
1. Vue 2 的 watch
选项
在Vue 2中,watch
是一个选项,用于监听data
或computed
中的属性变化。
基本语法:
export default {data() {return { count: 0 };},watch: {count(newValue, oldValue) {console.log(`count changed from ${oldValue} to ${newValue}`);}}
};
关键特性:
- 监听单个属性时,回调函数接收
(newValue, oldValue)
参数。 - 监听对象或数组时,默认是浅监听(需深度监听需设置
deep: true
)。 - 立即执行回调需设置
immediate: true
。
深度监听示例:
watch: {user: {handler(newValue, oldValue) {console.log('user changed:', newValue);},deep: true, // 深度监听对象内部变化immediate: true // 立即执行一次}
}
2. Vue 3 的 watch
(选项式API)
Vue 3的选项式API中,watch
的用法与Vue 2几乎一致。
示例:
import { defineComponent } from 'vue';
export default defineComponent({data() {return { count: 0 };},watch: {count(newValue, oldValue) {console.log(`count changed from ${oldValue} to ${newValue}`);}}
});
3. Vue 3 的 watch
(组合式API)
Vue 3的组合式API中,watch
通过函数形式导入,支持更灵活的监听逻辑(如监听多个源、计算属性等)。
基本语法:
import { ref, watch } from 'vue';
export default {setup() {const count = ref(0);watch(count, (newValue, oldValue) => {console.log(`count changed from ${oldValue} to ${newValue}`);});return { count };}
};
关键特性:
- 监听单个响应式源:直接传入
Ref
或reactive
对象。 - 监听多个源:传入数组。
- 立即执行:通过
{ immediate: true }
选项。 - 深度监听:默认对对象是浅监听,需显式设置
{ deep: true }
。
监听多个源示例:
import { ref, watch } from 'vue';
export default {setup() {const count = ref(0);const name = ref('');watch([count, name], ([newCount, newName], [oldCount, oldName]) => {console.log(`count: ${oldCount} -> ${newCount}, name: ${oldName} -> ${newName}`);});return { count, name };}
};
监听计算属性或复杂逻辑:
import { ref, computed, watch } from 'vue';
export default {setup() {const count = ref(0);const doubleCount = computed(() => count.value * 2);watch(doubleCount, (newValue) => {console.log('doubleCount changed:', newValue);});return { count };}
};
4. watchEffect
(Vue 3特有)
Vue 3引入了watchEffect
,它会自动追踪回调中用到的响应式依赖,无需显式声明监听目标。
示例:
import { ref, watchEffect } from 'vue';
export default {setup() {const count = ref(0);watchEffect(() => {console.log(`count is now: ${count.value}`);});return { count };}
};
与watch
的区别:
watchEffect
无需指定监听目标,自动追踪依赖。- 回调中用到的所有响应式变量变化时都会触发。
- 无法获取旧值(
oldValue
)。
5. TypeScript支持(Vue 3)
Vue 3的组合式API对TypeScript支持更好,可以显式声明监听数据的类型。
示例:
import { ref, watch } from 'vue';
export default {setup() {const count = ref<number>(0);watch(count, (newValue, oldValue) => {console.log(`count changed from ${oldValue} to ${newValue}`);});return { count };}
};
6. 性能优化对比
特性 | Vue 2 | Vue 3(选项式API) | Vue 3(组合式API) |
---|---|---|---|
监听单个属性 | watch 选项 | 同Vue 2 | watch(ref, callback) |
监听多个属性 | 需手动合并逻辑 | 同Vue 2 | watch([ref1, ref2], callback) |
深度监听 | deep: true | 同Vue 2 | { deep: true } 选项 |
立即执行 | immediate: true | 同Vue 2 | { immediate: true } 选项 |
自动依赖追踪 | 不支持 | 不支持 | watchEffect |
TypeScript支持 | 需额外类型声明 | 同Vue 2 | 内置类型推断,支持显式类型声明 |
7. 最佳实践建议
- 简单监听:Vue 2/Vue 3选项式API的
watch
选项足够。 - 复杂逻辑:Vue 3组合式API的
watch
更灵活(如监听多个源、计算属性)。 - 自动依赖追踪:优先使用
watchEffect
(适合无旧值需求的场景)。 - TypeScript项目:Vue 3组合式API能提供更好的类型安全。
完整示例对比
Vue 2 监听对象深度变化:
export default {data() {return { user: { name: 'Alice', age: 25 } };},watch: {user: {handler(newVal, oldVal) {console.log('user changed:', newVal);},deep: true,immediate: true}}
};
Vue 3 组合式API等价实现:
import { reactive, watch } from 'vue';
export default {setup() {const user = reactive({ name: 'Alice', age: 25 });watch(() => user,(newVal, oldVal) => {console.log('user changed:', newVal);},{ deep: true, immediate: true });return { user };}
};