Vue3 中 computed 计算属性与 watch、watchEffect 监听

发布时间:2026/8/2 18:10:36
Vue3 中 computed 计算属性与 watch、watchEffect 监听 1. 引言在 Vue3 开发中computed计算属性和watch监听器是两个非常常用的响应式工具。很多初学者容易混淆它们什么时候用 computed什么时候用 watch两者有什么区别和联系本文用通俗的语言、完整的案例和清晰的对比帮你彻底搞懂这两个属性。2. 什么是 computed 计算属性computed 的核心思想是根据已有的响应式数据派生出一个新的值。它就像一个“自动计算的公式”只要依赖的数据发生变化计算属性就会自动重新计算并且结果会被缓存。通俗理解computed 是“声明式”的你告诉 Vue“我想要什么”Vue 自动帮你算好。它适合用在模板中展示经过加工的数据。2.1 基础案例下面是一个购物车总价的例子template div p商品单价{{ price }} 元/p p购买数量{{ count }} 件/p p总价{{ totalPrice }} 元/p button clickcount增加数量/button /div /template script setup import { ref, computed } from vue const price ref(100) const count ref(1) // 计算属性根据 price 和 count 自动派生总价 // 为什么这里可以写箭头函数呢因为vue3 setup里没有this const totalPrice computed(() { return price.value * count.value }) /script在这个例子中totalPrice不需要手动维护只要price或count变化它就会自动更新。而且只要依赖不变多次访问totalPrice会直接返回缓存结果不会重复计算。2.2 computed 的特点有缓存依赖不变时多次读取不会重复执行计算函数性能更好。只读默认计算属性默认只能读取不能直接修改。如果确实需要修改要使用带 getter 和 setter 的写法。适合模板展示把复杂的逻辑从模板中抽离出来让模板更简洁。下面来证明computed的特点1. 有缓存不重复执行计算函数在模板上调用6次计算属性每调用一次计算方法打印输出1在控制台只输出了一次下面是通过方法来实现发现控制台打印了6次。2. 只读通过getter和setter修改3. 什么是 watch 监听器watch 的核心思想是监听某个数据的变化当它变化时执行一段副作用逻辑。它更像一个“哨兵”一旦发现目标变化就触发你预先定义好的回调函数。和vue2的作用一致但写法有区别。watch 可以监听以下几种情况监视 【ref】定义的【基本类型】数据ref 需要手动开启深度监视监视 【ref】定义的【对象类型】数据,ref 需要手动开启深度监视监视【reactive】定义的【对象类型】数据且默认是开启深度监视的, 并且无法关闭监视 ref 或 reactive 定义的【对象类型】数据中的某个属性监视上述的多个数据什么时候开启深度监视只有要监视对象内部属性时需要开启通俗理解watch 是“命令式”的你告诉 Vue“当某个东西变了去做某件事”。它适合处理异步操作、请求接口、操作 DOM 等有副作用的场景。3.1 基础案例情况一:监视ref定义的【基本类型】数据直接写数据名即可不用写.value但监视的是其value值的改变当监视的值 10, 停止监视watch调用的返回值stopwatch是用于停止监听的函数情况二监视 ref 定义的【对象类型】数据: 直接写数据名监视的是对象的【地址值】若想监视对象内部的数据要手动开启深度监视。若修改整个 ref 定义的对象的属性newValue 和 oldValue 都是新值因为它们是同一个对象。若修改整个 ref 定义的对象newValue 是新值oldValue 是旧值因为不是同一个对象了情况三监视【reactive】定义的【对象类型】数据且默认是开启深度监视的, 并且无法关闭情况四监视 ref 或 reactive 定义的【对象类型】数据中的某个属性注意点如下:1.若该属性值不是【对象类型】需要写成函数形式。2.若该属性值是依然是【对象类型】可直接编也可写成函数不过建议写成函数。1. 监听的属性值不是对象类型监听person对象里的name属性因为name不是对象所以写成函数形式。2.监听的属性值是对象类型2.1 直接写对象的写法可以监听到对象属性里面的某个属性但整个对象无法监听。2.2 函数式可以监听整个对象地址但对象里面的某个属性无法监听。2.3既要监听对象某个属性又要监听整个对象。需要写成函数式然后开启深度监视情况五监视上述的多个数据需要写成数组的形式并且数组里监听的对象要不要写成函数式看监听的是对象还是基本数据类型基本数据类型需要写成函数式对象类型推荐写成函数式。可以看到newValue监听的是整个数组不是数组中某个属性3.2 watch 的特点无缓存每次数据变化都会触发回调没有缓存机制。适合副作用异步请求、DOM 操作、日志记录等场景。可监听多个数据可以同时监听一个或多个响应式数据。支持深度监听监听对象内部属性变化时需要开启deep选项。4. watchEffect 监听器watchEffect 和 watch同样是监听作用区别在于watchEffect会立即执行一次函数并且不需要指定监听哪些对象和属性watchEffect会自动分析监听哪些而watch要指定监听哪些属性和对象才行。下面案例可以看到如果使用watch需要先指定对哪些对象进行监听而watchEffect不需要指定watchEffect会自动帮我们分析监听哪些。5. computed 与 watch 的对比为了更直观地理解两者的区别下面从多个维度进行对比。5.1 核心区别对比表对比维度computed 计算属性watch 监听器核心思想根据已有数据派生新值监听数据变化并执行副作用使用方式声明式告诉 Vue 想要什么命令式告诉 Vue 变化后做什么是否有缓存有缓存依赖不变不重复计算无缓存每次变化都触发返回值返回一个派生值可直接用于模板不返回值只执行回调逻辑适用场景模板中展示加工后的数据异步请求、DOM 操作、复杂逻辑是否支持异步不支持计算函数应为纯函数支持可在回调中执行异步操作能否修改默认只读可配置 setter不涉及修改只负责响应变化5.2 联系与联系点虽然两者用途不同但它们也有紧密的联系都基于响应式系统computed 和 watch 都依赖 Vue3 的响应式机制能自动追踪数据依赖。都能感知数据变化两者都能在依赖数据变化时做出反应只是反应方式不同。可以配合使用在实际项目中经常先用 computed 派生数据再用 watch 监听这个派生结果去执行副作用。5.3 配合使用的案例下面演示 computed 和 watch 如何协同工作script setup import { ref, computed, watch } from vue const price ref(100) const count ref(1) // computed派生总价 const totalPrice computed(() price.value * count.value) // watch监听总价变化执行副作用比如上报埋点 watch(totalPrice, (newTotal) { console.log(总价变化为, newTotal) // 这里可以发送埋点请求或执行其他副作用 }) /script在这个例子中computed 负责“算”watch 负责“听”。当总价变化时watch 自动触发埋点上报两者各司其职、配合默契。6. 如何选择什么时候用哪个选择原则可以总结为一句话需要多次显示用computed而不用方法能用 computed 解决的优先用 computed需要执行副作用的才用 watch。如果只是想展示一个派生值如总价、过滤后的列表、拼接后的字符串用 computed。如果需要在数据变化时执行一段逻辑如请求接口、操作 DOM、保存草稿用 watch。如果既要派生数据又要在派生结果变化时做额外处理两者配合使用。7. 总结computed 和 watch 是 Vue3 响应式体系中的两大核心工具。computed 擅长“算”用声明式的方式从已有数据派生新值自带缓存适合模板展示watch 擅长“听”用命令式的方式监听数据变化并执行副作用适合异步和复杂逻辑。理解两者的区别和联系能让你在开发中写出更清晰、更高效的代码。