Vue3监听数据变化方法详解
在 Vue 3 中,监听数据变化主要依赖 watch
和 watchEffect
两个 API,它们都属于 Composition API 的一部分。以下是详细的用法和区别:
一、watch
的基本用法
作用:显式监听特定数据源,在数据变化时执行回调函数。
1. 监听单个数据源
javascript
复制
import { ref, watch } from 'vue';const count = ref(0);// 监听 ref watch(count, (newVal, oldVal) => {console.log(`count变化: ${oldVal} → ${newVal}`); });
2. 监听 reactive 对象的属性
javascript
复制
import { reactive, watch } from 'vue';const state = reactive({ user: { name: 'Alice', age: 30 } });// 监听对象属性(需用 getter 函数) watch(() => state.user.age,(newVal, oldVal) => {console.log(`年龄变化: ${oldVal} → ${newVal}`);} );
3. 监听多个数据源
javascript
复制
const a = ref(1); const b = ref(2);watch([a, b], ([newA, newB], [oldA, oldB]) => {console.log(`a: ${oldA}→${newA}, b: ${oldB}→${newB}`); });
4. 深度监听(deep)
默认情况下,watch
是浅层监听。对嵌套对象需开启 deep: true
:
javascript
复制
watch(() => state.user,(newUser) => {console.log('用户信息变化(包括嵌套属性):', newUser);},{ deep: true } );
5. 立即执行(immediate)
在监听开始后立即触发回调:
javascript
复制
watch(count,(newVal) => {console.log('初始值:', newVal);},{ immediate: true } );
二、watchEffect
的用法
作用:自动跟踪依赖,并在依赖变化时立即执行副作用函数。
1. 基本使用
javascript
复制
import { ref, watchEffect } from 'vue';const count = ref(0);// 自动追踪 count 的变化 watchEffect(() => {console.log('当前count值:', count.value); });
2. 自动聚合依赖
无需手动指定依赖,函数内使用的响应式变量会被自动追踪:
javascript
复制
const a = ref(1); const b = ref(2);watchEffect(() => {console.log('a + b =', a.value + b.value); }); // 修改 a 或 b 都会触发
3. 清理副作用
通过返回一个函数来清理副作用(如定时器、事件监听):
javascript
复制
watchEffect((onCleanup) => {const timer = setInterval(() => {console.log('每秒执行');}, 1000);onCleanup(() => clearInterval(timer)); });
三、watch
vs watchEffect
特性 | watch | watchEffect |
---|---|---|
依赖指定 | 显式指定数据源 | 自动追踪回调内的响应式依赖 |
初始执行 | 默认不执行(可配置 immediate ) | 立即执行 |
适用场景 | 需要精确控制监听的数据源 | 依赖变化时自动执行聚合逻辑 |
深度监听 | 需手动开启 deep: true | 自动追踪嵌套属性(类似 deep) |
四、停止监听器
通过调用 watch
或 watchEffect
返回的函数来停止监听:
javascript
复制
const stop = watchEffect(() => { /* ... */ });// 停止监听 stop();
在组件卸载时自动停止:
javascript
复制
import { onUnmounted } from 'vue';setup() {const stop = watchEffect(() => { /* ... */ });onUnmounted(stop); }
五、实用场景示例
1. 搜索输入防抖(watch)
javascript
复制
const searchQuery = ref(''); let timeoutId;watch(searchQuery, (newQuery) => {clearTimeout(timeoutId);timeoutId = setTimeout(() => {fetchResults(newQuery);}, 500); });
2. 自动保存表单(watchEffect)
javascript
复制
const form = reactive({ title: '', content: '' });watchEffect((onCleanup) => {// 自动追踪 form.title 和 form.contentconst autoSave = setTimeout(() => {saveToServer(form);}, 3000);onCleanup(() => clearTimeout(autoSave)); });
六、注意事项
-
避免无限循环:在监听回调中修改被监听的数据可能导致循环,需谨慎。
-
性能优化:避免过度使用
deep: true
,尤其是大型对象。 -
异步操作:在回调中进行异步操作时,使用
onCleanup
清理未完成的请求。
掌握这些技巧后,你可以更灵活地利用 Vue 3 的响应式系统构建高效应用!