Skip to content

计算属性(computed)和侦听器(watch)

计算属性和侦听器是 Vue 响应式系统中的核心功能,用于处理依赖数据的逻辑和副作用。以下是它们的详细对比和使用场景:

计算属性(computed)

作用

  • 基于依赖数据动态计算值,并缓存结果。
  • 只有当依赖的响应式数据变化时,才会重新计算。

语法

javascript
import { ref, computed } from 'vue';

const firstName = ref('张');
const lastName = ref('三');
const fullName = computed(() => `${firstName.value} ${lastName.value}`);

特点

  1. 缓存机制

    • 只有当 firstNamelastName 变化时,fullName 才会重新计算。
    • 多次访问 fullName 直接返回缓存值,避免重复计算。
  2. 只读性

    • 默认生成的是只读属性,不能直接赋值。

    • 如需可写,需提供 getset

      javascript
      const fullName = computed({
        get() { return `${firstName.value} ${lastName.value}`; },
        set(newValue) { 
          [firstName.value, lastName.value] = newValue.split(' ');
        }
      });
  3. 适用场景

    • 模板中需要复杂逻辑计算的表达式(如过滤列表、格式化数据)。
    • 避免在模板中写复杂逻辑,保持代码清晰。

示例

html
<template>
  <p>全名:{{ fullName }}</p>
</template>

侦听器(watch)

作用

  • 监听响应式数据的变化,执行副作用(如异步请求、DOM 操作)。
  • 适合处理数据变化后的异步或复杂逻辑。

语法

javascript
import { ref, watch } from 'vue';

const count = ref(0);
const user = ref({ name: 'Alice' });

// 监听单个 ref
watch(count, (newVal, oldVal) => {
  console.log(`count 变化:${oldVal} → ${newVal}`);
});

// 监听嵌套属性
watch(
  () => user.value.name,
  (newName) => {
    console.log(`用户名变为 ${newName}`);
  }
);

// 监听多个源
watch([count, () => user.value.name], ([newCount, newName]) => {
  console.log(`count或name变化:${newCount}, ${newName}`);
});

特点

  1. 惰性执行

    • 默认不会立即执行,只有在监听的数据变化时触发。
    • 通过 { immediate: true } 强制立即执行一次。
  2. 深度监听

    • 默认不监听对象内部变化,需设置 { deep: true }

      javascript
      watch(user, (newVal) => { 
        console.log('user 变化', newVal);
      }, { deep: true });
  3. 停止监听

    • 组合式 API 中,watch 返回一个停止函数:

      javascript
      const stop = watch(count, () => { /*...*/ });
      stop(); // 手动停止监听
  4. 适用场景

    • 数据变化时需要执行异步操作(如搜索请求)。
    • 监听路由或状态变化后执行逻辑。

示例

javascript
// 搜索框输入防抖
const searchQuery = ref('');
watch(searchQuery, (newQuery) => {
  fetchResults(newQuery); // 模拟 API 请求
}, { debounce: 300 }); // 300ms 防抖

computed 和 watch 对比

特性computedwatch
目的派生新数据(基于依赖计算)监听数据变化执行副作用
返回值必须返回一个值无返回值(通常执行异步操作)
缓存✅ 自动缓存结果❌ 每次变化都触发
异步支持❌ 不能包含异步逻辑✅ 适合异步操作
典型场景模板中的动态计算(如全名)数据变化后调 API、操作 DOM

如何选择?

  • computed 当:

    • 需要基于其他数据 动态计算一个值(如过滤列表、格式化显示)。
    • 希望利用缓存优化性能。
  • watch 当:

    • 需要在数据变化时 执行副作用(如请求 API、存储到 localStorage)。
    • 需要监听 非响应式数据(如路由参数)。

组合使用示例

javascript
import { ref, computed, watch } from 'vue';

const price = ref(100);
const quantity = ref(2);

// 计算总价(自动缓存)
const total = computed(() => price.value * quantity.value);

// 监听总价变化
watch(total, (newTotal) => {
  console.log('总价更新:', newTotal);
  if (newTotal > 500) {
    alert('金额过大!');
  }
});

总结

  • computed
    • 计算派生数据,适合模板中使用。
    • 自动缓存,高效响应依赖变化。
  • watch
    • 监听数据变化,执行异步或副作用逻辑。
    • 支持深度监听、防抖等高级功能。
编程洪同学服务平台是一个广泛收集编程相关内容和资源,旨在满足编程爱好者和专业开发人员的需求的网站。无论您是初学者还是经验丰富的开发者,都可以在这里找到有用的信息和资料,我们将助您提升编程技能和知识。
专业开发
高端定制
售后无忧
站内资源均为本站制作或收集于互联网等平台,如有侵权,请第一时间联系本站,敬请谅解!本站资源仅限于学习与参考,严禁用于各种非法活动,否则后果自行负责,本站概不承担!