小记-vue3 watch 和 watchEffect 有什么区别

181 阅读2分钟

初次使用vue3使用这两个api的时候感觉好像没有什么特别大的区别,我写个小记 给自己整理一下加深一下印象

在 Vue 3 中,watch 和 watchEffect 都是用于监听数据变化的 API,但它们有一些重要的区别:

1.用途:

watch:用于监听一个或多个特定的响应式数据源的变化,并在变化时执行对应的回调函数。他适用于需要再数据变化的时候执行某些副作用逻辑的场景
watchEffect:用于自动监听其内部使用的所有响应式数据源的变化,并在这些数据变化时重新运行。他适用于需要简化副作用逻辑的场景

2. 参数:

`watch:接受两个参数,第一个是要监听的响应式数据或getter函数,第二个是回调函数`

```js
    watch(source,(newVal,oldValue) => {
    // 处理变化
    })
```
`watchEffect: 只接受一个回调函数,内部会自动追踪适用的响应式数据`
```js
    watchEffect(()=> {
        // 使用的响应式数据会被自动追踪
    })
```

3. 执行时机:

```
watch: 只在监听的源数据发生变化时执行回调`
watchEffect:在组件创建时立即执行一次回调,并在任何依赖的数据变化时自动重新执行
```

4. 适用场景

```
watch: 更适合处理复杂的逻辑、多个数据源的变化时需要使用之前的值
watchEffect:更适合简单的副作用逻辑,尤其是在数据依赖关系较为直接的情况下。
```

示例代码

// 使用watch:
import { ref, watch } from 'vue';
const count = ref(0);
watch(count, (newValue, oldValue) => {
  console.log(`Count changed from ${oldValue} to ${newValue}`);
});
// 使用watchEffect
import { ref, watchEffect } from 'vue';

const count = ref(0);
watchEffect(() => {
  console.log(`Count is: ${count.value}`);
});

什么是副作用逻辑

副作用逻辑是指在执行某个操作时,除了计算和返回一个值之外,还会对外部状态产生影响的行为。这些影响通常包括对其他变量的修改、调用 API、更新 UI、设置定时器等。

在 Vue 3 中,副作用逻辑的场景一般包括以下几种:

1.数据获取

// 从服务器获取数据并更新组件状态。
watch(userInfoId, async (newUserInfoId) => {
  const response = await fetch(`/api/users/${newUserInfoId}`);
  user.value = await response.json();
});

2.手动DOM操作

// 不管在vue2还是vue3中,通常都不建议直接操作DOM,但有时会有特殊场景需要调整
watch(isVisible, (newValue) => {
  if (newValue) {
    document.getElementById('element').style.display = 'block';
  } else {
    document.getElementById('element').style.display = 'none';
  }
});

3. 定时器或者延时操作

// 数据变化时和设置定时器执行操作
watch(count, (newValue) => {
  setTimeout(() => {
    console.log(`Count after 1 second: ${newValue}`);
  }, 1000);
});

4.错误处理或者状态提示

// 根据某个状态变化显示错误提示或加载状态
watch(isLoading, (loading) => {
    if (loading) { 
        showLoadingIndicator();
    } else {
        hideLoadingIndicator();
    } 
});

5.数据持久化

 // 数据变化时,将状态保存到本地存储或数据库中
 watch(userInfo, (newUserInfo) => {
  localStorage.setItem('app-user_info', JSON.stringify(newUserInfo));
}, { deep: true });