Vue中的computed和watch的区别是什么

发布时间:2021-12-07 19:48:56 作者:柒染
来源:亿速云 阅读:191
# Vue中的computed和watch的区别是什么

## 引言

在Vue.js开发中,`computed`(计算属性)和`watch`(侦听器)是两种常用的响应式数据处理机制。虽然它们都能观察数据变化并执行相应操作,但设计理念和使用场景存在显著差异。本文将深入剖析两者的核心区别,涵盖原理、语法、性能、应用场景等维度,并附实战案例和最佳实践建议。

---

## 一、核心概念解析

### 1.1 computed(计算属性)

**定义**:  
计算属性是基于它们的响应式依赖进行缓存的派生值,只有在相关依赖发生改变时才会重新计算。

**核心特点**:
- **声明式编程**:描述"应该是什么"
- **依赖追踪**:自动检测依赖关系
- **缓存机制**:相同依赖不重复计算

```javascript
export default {
  data() {
    return { firstName: '张', lastName: '三' }
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName
    }
  }
}

1.2 watch(侦听器)

定义
侦听器用于观察和响应Vue实例上的数据变动,适合执行异步或开销较大的操作。

核心特点: - 命令式编程:描述”当什么发生时做什么” - 显式监听:需要指定具体监听目标 - 无缓存:每次变化都会触发回调

export default {
  data() {
    return { question: '', answer: '' }
  },
  watch: {
    question(newVal, oldVal) {
      this.getAnswer()
    }
  }
}

二、核心区别对比

2.1 设计目的差异

维度 computed watch
定位 派生状态 副作用管理
关注点 “值是什么” “值变化时做什么”
范式 声明式 命令式

2.2 执行机制对比

computed执行流程: 1. 建立依赖关系(通过getter收集) 2. 依赖变化时标记为”dirty” 3. 下次访问时重新计算

watch执行流程: 1. 立即执行(除非设置immediate: false) 2. 深度监听可检测嵌套变化(deep: true) 3. 回调函数同步/异步执行

2.3 语法结构差异

computed典型写法

computed: {
  // 简写形式
  double() {
    return this.count * 2
  },
  
  // 完整形式
  triple: {
    get() {
      return this.count * 3
    },
    set(val) {
      this.count = val / 3
    }
  }
}

watch典型写法

watch: {
  // 基本形式
  count(newVal, oldVal) {
    console.log(`从${oldVal}变为${newVal}`)
  },
  
  // 深度监听
  user: {
    handler(newVal) {
      console.log('用户信息变化', newVal)
    },
    deep: true,
    immediate: true
  },
  
  // 监听对象属性
  'user.name': {
    handler(newVal) {
      console.log('用户名变化', newVal)
    }
  }
}

2.4 性能特征对比

场景 computed优势 watch优势
高频访问 缓存避免重复计算 -
异步操作 不适合 适合
复杂计算 自动依赖追踪 需要手动管理依赖
DOM更新 在同一个tick中完成 可能跨多个tick

三、应用场景深度解析

3.1 computed最佳使用场景

场景1:模板复杂逻辑封装

<template>
  <div>
    商品总价:{{ formattedTotalPrice }}
  </div>
</template>

<script>
export default {
  computed: {
    formattedTotalPrice() {
      return '¥' + (this.quantity * this.unitPrice).toFixed(2)
    }
  }
}
</script>

场景2:多条件过滤

computed: {
  filteredProducts() {
    return this.products.filter(
      p => p.price <= this.maxPrice && 
           p.category === this.selectedCategory
    )
  }
}

3.2 watch最佳使用场景

场景1:API异步请求

watch: {
  searchQuery(newVal) {
    clearTimeout(this.timer)
    this.timer = setTimeout(() => {
      this.fetchResults(newVal)
    }, 500)
  }
}

场景2:路由参数监听

watch: {
  '$route.params.id'(newId) {
    this.fetchUserDetail(newId)
  }
}

场景3:表单验证联动

watch: {
  'form.email'(newVal) {
    this.validateEmail(newVal)
  }
}

四、高级用法与边界情况

4.1 computed的setter用法

computed: {
  fullName: {
    get() {
      return `${this.firstName} ${this.lastName}`
    },
    set(newValue) {
      const names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[1] || ''
    }
  }
}

4.2 watchEffect与watch的区别

import { watchEffect, watch } from 'vue'

// 自动追踪依赖
watchEffect(() => {
  console.log('count变化:', this.count)
})

// 需要明确指定监听源
watch(
  () => this.count,
  (newVal, oldVal) => {
    console.log(`从${oldVal}变为${newVal}`)
  }
)

4.3 性能优化技巧

  1. 避免computed过度计算
// 反模式:每次都会创建新数组
computed: {
  bigArray() {
    return new Array(1000000).fill(0)
  }
}
  1. 合理使用watch的flush选项
watch: {
  value: {
    handler() { /*...*/ },
    flush: 'post' // DOM更新后触发
  }
}

五、综合对比表格

对比维度 computed watch
触发时机 依赖变化后下次访问时 监听目标变化时立即触发
返回值 必须返回结果 无返回值要求
异步支持 天然不支持 原生支持
初始化执行 延迟执行(惰性求值) 可通过immediate: true立即执行
多个依赖 自动关联所有依赖 需手动指定每个监听源
代码组织 集中管理派生状态 分散在各个回调中
调试难度 较难(自动依赖追踪) 较易(明确触发逻辑)

六、实战中的选择策略

6.1 选择computed当:

6.2 选择watch当:

6.3 组合使用案例

export default {
  data() {
    return {
      userId: null,
      user: null,
      isAdmin: false
    }
  },
  computed: {
    userProfile() {
      return this.user ? `${this.user.name} (${this.user.email})` : '未登录'
    }
  },
  watch: {
    userId: {
      immediate: true,
      async handler(newVal) {
        if (newVal) {
          this.user = await fetchUser(newVal)
          this.isAdmin = this.user.role === 'admin'
        }
      }
    }
  }
}

七、常见误区与陷阱

  1. 在computed中修改依赖数据
// 反模式:导致无限循环
computed: {
  badExample() {
    this.count++ // 错误!
    return this.count * 2
  }
}
  1. 忽略watch的深度监听成本
watch: {
  bigObject: {
    handler() { /*...*/ },
    deep: true // 对大对象性能影响显著
  }
}
  1. 混淆computed和methods
// 不恰当的方法使用
methods: {
  calculatedValue() {
    return this.a + this.b // 每次渲染都会计算
  }
}

八、Vue 3中的变化

  1. Composition API中的实现
import { computed, watch, ref } from 'vue'

setup() {
  const count = ref(0)
  
  const double = computed(() => count.value * 2)
  
  watch(count, (newVal) => {
    console.log('count changed', newVal)
  })
  
  return { count, double }
}
  1. watch与watchEffect的区别

结语

理解computedwatch的本质区别,能帮助开发者更合理地组织Vue应用中的响应式逻辑。计算属性适合派生状态的声明式组合,而侦听器则擅长处理变化触发的命令式操作。在实际项目中,两者往往需要配合使用,共同构建健壮的响应式系统。

关键记忆点:
- 计算属性是声明式的值计算
- 侦听器是命令式的变化响应
- 选择依据:是否需要缓存?是否需要副作用? “`

该文档共计约3700字,采用Markdown格式编写,包含: 1. 多级标题结构 2. 对比表格3个 3. 代码示例8个 4. 列表项20+ 5. 强调文本多处 6. 覆盖Vue 2/3特性 7. 实用场景分析 8. 性能优化建议

推荐阅读:
  1. Vue中methods computed 和 watch 的区别
  2. Vue中Computed和Watch的区别及其用法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue computed watch

上一篇:网站开发中网站打开速度慢怎么解决

下一篇:vscode中如何将cmd设置为默认终端

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》