Vue 中 computed 和 watch 的差异
本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
应用实时监控服务ARMS - 应用监控,每月50GB免费额度
简介:
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
- 定义与基本功能
- computed(计算属性)
- 定义:计算属性是基于Vue实例的响应式数据(如
data
中的属性)进行计算得到的值。它会根据依赖的数据自动缓存计算结果,只有当依赖的数据发生变化时,才会重新计算。
- 示例:假设我们有一个商品列表,每个商品有价格和数量,我们想计算总价。可以在Vue组件中这样定义计算属性:
export default {
data() {
return {
products: [
{
price: 10, quantity: 2},
{
price: 20, quantity: 3}
]
};
},
computed: {
totalPrice() {
return this.products.reduce((total, product) => {
return total + (product.price * product.quantity);
}, 0);
}
}
}
- watch(侦听器)
- 定义:侦听器主要用于观察和响应Vue实例中数据的变化。当被观察的数据发生变化时,会执行相应的回调函数。它更侧重于数据变化后的异步操作或副作用。
- 示例:如果我们想在用户输入的搜索关键词变化时,发送一个API请求获取相关商品列表,可以这样使用侦听器:
export default {
data() {
return {
searchTerm: '',
productList: []
};
},
watch: {
searchTerm(newValue, oldValue) {
this.fetchProducts(newValue);
}
},
methods: {
fetchProducts(term) {
axios.get(`/api/products?search=${
term}`).then(response => {
this.productList = response.data;
});
}
}
}
- 依赖追踪与更新机制
- computed
- 依赖追踪:计算属性会自动追踪其内部使用的响应式数据作为依赖。在上述总价计算的例子中,
totalPrice
计算属性依赖于products
数组中的每个product
对象的price
和quantity
属性。Vue会自动检测这些依赖,当其中任何一个依赖发生变化时,就会重新计算totalPrice
。
- 缓存机制:计算属性具有缓存特性。如果多次访问计算属性,只要其依赖的数据没有变化,就会直接返回缓存的结果,而不会重新计算。这在性能上是很有优势的,特别是当计算过程比较复杂时。例如,计算属性
totalPrice
在组件首次渲染时计算一次,只要products
数据没有变化,后续对totalPrice
的访问都会使用缓存的结果。
- watch
- 手动观察特定数据:与计算属性不同,
watch
需要手动指定要观察的数据。在watch
选项中定义的每个属性,就是要观察的数据。当这些数据发生变化时,对应的回调函数就会被执行。例如,在搜索关键词的例子中,我们明确地告诉Vue要观察searchTerm
数据的变化。
- 每次变化都执行回调:只要被观察的数据发生变化,
watch
中的回调函数就会执行。它不会像计算属性那样缓存结果,每次变化都会触发相应的操作。这使得watch
更适合用于处理数据变化后的异步操作,如发送网络请求、更新外部存储等。
- 使用场景与最佳实践
- computed
- 适用于数据的派生计算:当需要根据已有的响应式数据计算出一个新的值,并且这个值在模板中需要频繁使用时,计算属性是很好的选择。例如,格式化日期、拼接字符串、计算复杂的数学公式等场景。除了前面提到的总价计算,还可以用于将用户输入的姓名和姓氏拼接成完整姓名等操作。
- 保持计算逻辑的纯净性:计算属性应该只用于计算,不应该产生副作用。它的计算结果应该只依赖于响应式数据,并且不应该修改这些数据。这样可以保证计算属性的行为是可预测的,便于调试和维护。
- watch
- 响应数据变化后的异步操作:当需要在数据变化后执行异步操作,如与后端API交互、操作DOM(虽然在Vue中尽量避免直接操作DOM)等,
watch
是合适的工具。例如,在用户修改表单数据后,实时验证数据并向用户反馈验证结果;或者在地图组件中,当用户缩放级别变化时,重新加载地图数据。
- 深度观察复杂数据结构:对于复杂的数据结构(如嵌套对象或数组),可以通过设置
deep
选项来深度观察数据的变化。不过,深度观察可能会导致性能问题,因为它会递归地检查数据的每一个子属性。所以在使用时要谨慎考虑,只有当确实需要对复杂数据结构的所有变化做出响应时才使用。