前言

在 Vue 的响应式世界里,computed(计算属性)和 watch(侦听器)是我们处理数据联动最常用的两把利器。虽然它们都能响应数据变化,但背后的设计哲学和应用场景却大相径庭。本文将结合 Vue 3 组合式 API 与 TypeScript,带你理清两者的本质区别。

一、 Computed:智能的“数据加工厂”

computed 的核心在它是一个计算属性。它会根据所依赖的数据动态计算结果,并具备强大的缓存机制。

1. 核心特性

  • 具备缓存性:只有当它依赖的响应式数据发生变化时,才会重新计算。否则,无论多少次访问该属性,都会立即返回上次缓存的结果。
  • 必须有返回值:它必须通过 return 返回计算后的结果。
  • 惰性求值:只有在被读取时才会执行计算。

2. Vue 3 + TS 示例

<script setup lang="ts">
import { ref, computed } from 'vue';

const count = ref<number>(1);

// computedValue1 为计算出的新属性
const computedValue1 = computed<number>(() => {
  console.log('正在执行计算...'); // 只有 count 改变时才会打印
  return count.value + 1;
});
</script>

<template>
  <div>原值: {{ count }} | 计算值: {{ computedValue1 }}</div>
  <button @click="count++">增加</button>
</template>

二、 Watch:敏锐的“数据坚控员”

watch 的核心在于响应副作用。当的值发生改变时执行特定的回调函数。

1. 核心特性

  • 无缓存性:它不是为了产生新值,而是为了在值变化时执行逻辑。

  • 无返回值:回调函数中通常处理的是异步操作、修改 DOM 或更改其他状态。

  • 配置灵活

    • immediate:设置为 true 时,在初始化时立即执行一次。
    • deep:设置为 true 时,可以深度对象内部属性的变化。

2. Vue 3 + TS 示例

<script setup lang="ts">
import { ref, watch } from 'vue';

interface UserInfo {
  name: string;
  age: number;
}

const user = ref<UserInfo>({ name: '张三', age: 25 });

// 对象深度变化
watch(
  user,
  (newVal, oldVal) => {
    // 注意:由于是引用类型,newVal 和 oldVal 指向的是同一个对象,只有开启deep: true才能到
    console.log('用户信息变了', newVal.age);
  },
  { 
    deep: true,      // 开启深度
    immediate: false // 初始化时不立即执行
  }
);
</script>

三、 扩展:Vue 3 中的 WatchEffect

在 Vue 3 中,除了 watch,还有一个更自动化的 watchEffect

  • 区别watchEffect 不需要手动指定哪个属性,它会自动收集回调函数中用到的所有响应式变量。
  • 场景:当你需要在一个函数里用到多个响应式数据,且不关心旧值时,watchEffect 代码更简洁。
<script setup lang="ts">
import { ref, watchEffect } from 'vue';

const user = ref({ name: '张三', age: 25 });

// watchEffect 会自动追踪依赖
watchEffect(() => {
  console.log('watchEffect  age:', user.value.age);
  // 自动收集 user.value.age 作为依赖
  // 当 age 变化时会自动执行
});
</script>

四、 深度对比:我该选哪一个?

特性Computed (计算属性)Watch (侦听器)
主要功能生成一个新属性(派生状态)响应数据变化并执行代码(副作用)
缓存有缓存,依赖不变不计算无缓存,变化即触发
异步不支持异步逻辑支持异步操作(如接口请求)
代码结构必须有 return不需要 return
使用场景格式化数据、多值组合、性能优化异步数据请求、手动操作 DOM、路由变化
本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com