Vue 中 watch 和 computed 深度对比及使用场景分析

一、核心机制对比

特性Computed(计算属性)Watch(侦听器)
原理基于依赖的响应式缓存观察特定数据变化,触发回调函数
触发时机依赖的响应式数据变化时自动计算被侦听的特定数据变化时触发
返回值必须有返回值,用于模板渲染或逻辑处理无返回值,用于执行副作用操作(如异步请求、DOM操作)
异步支持❌ 不能执行异步操作✅ 支持异步操作
缓存机制✅ 依赖未变化时直接返回缓存结果,高效❌ 无缓存,每次变化都执行回调
适用场景模板中需要复杂逻辑处理的数据数据变化时需要执行特定操作(如接口请求、复杂逻辑)

二、使用场景及代码示例

1. Computed 适用场景

场景特点:需要基于现有数据 派生新值,且依赖数据变化时需要 自动更新

示例 1:格式化显示数据

<template>
  <div>全名:{{ fullName }}</div>
</template>

<script>
export default {
  data() {
    return { firstName: '张', lastName: '三' };
  },
  computed: {
    fullName() {
      return this.firstName + '·' + this.lastName; // 自动拼接
    }
  }
};
</script>

示例 2:过滤列表数据

<template>
  <div v-for="item in filteredList" :key="item.id">{{ item.name }}</div>
</template>

<script>
export default {
  data() {
    return {
      list: [/* 原始数据 */],
      searchText: ''
    };
  },
  computed: {
    filteredList() {
      return this.list.filter(item => 
        item.name.includes(this.searchText)
      );
    }
  }
};
</script>

2. Watch 适用场景

场景特点:需要在数据变化时 执行异步操作复杂副作用

示例 1:搜索输入防抖(异步操作)

<script>
export default {
  data() {
    return { searchText: '' };
  },
  watch: {
    searchText(newVal) {
      // 防抖处理,避免频繁请求
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.fetchData(newVal);
      }, 500);
    }
  },
  methods: {
    fetchData(keyword) { /* 发起请求 */ }
  }
};
</script>

示例 2:深度监听对象变化

<script>
export default {
  data() {
    return { user: { name: 'Alice', age: 25 } };
  },
  watch: {
    user: {
      handler(newVal) {
        console.log('用户信息变化:', newVal);
      },
      deep: true, // 深度监听对象内部变化
      immediate: true // 立即触发一次
    }
  }
};
</script>

三、Vue 3 中的变化(Composition API)

1. Computed
import { ref, computed } from 'vue';

const firstName = ref('张');
const lastName = ref('三');

const fullName = computed(() => {
  return firstName.value + '·' + lastName.value;
});
2. Watch
import { ref, watch } from 'vue';

const searchText = ref('');

watch(searchText, (newVal, oldVal) => {
  // 执行异步操作
  fetchData(newVal);
});

// 监听多个源
watch([source1, source2], ([new1, new2], [old1, old2]) => {});
3. WatchEffect(自动依赖追踪)
import { watchEffect } from 'vue';

watchEffect(() => {
  // 自动追踪函数内使用的响应式变量
  console.log('searchText变化:', searchText.value);
});

四、性能优化建议

  1. 优先使用 Computed
    • 避免在模板中写复杂逻辑,用 Computed 缓存结果。
  2. 避免深度监听(Watch)的开销
    • 必要时使用 deep: true,但需注意性能影响。
  3. 及时清理副作用
    • 在组件销毁前,清除定时器或取消未完成的异步操作(如 clearTimeout)。

五、总结

维度ComputedWatch
核心目的派生数据(模板渲染、数据格式化)响应数据变化(执行副作用操作)
缓存有缓存,依赖不变时复用结果无缓存,每次变化都执行
异步不支持支持
适用场景模板中的复杂逻辑、数据过滤/聚合数据变化时需要异步操作或触发其他行为

选择原则

  • 需要派生数据 → 用 computed
  • 需要响应变化执行操作 → 用 watch
  • Vue 3 组合式 API → 灵活使用 computedwatchwatchEffect

经典场景

  • 计算总价、格式化日期 → computed
  • 搜索框输入防抖、路由参数变化重新加载数据 → watch
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值