结论先行:
computed 是计算属性,有缓存功能。它的底层会通过 dirty 变量来判断是否重新计算。只有在依赖数据发生变化时才会重新计算,性能会更好。
而 watch 没缓存,但 watch 能执行异步和比较复杂的逻辑操作。
在应用场景上的区别:
computed 适用于多对一,也就是这个缓存属性受多个属性影响,例如购物车商品结算;
而 watch 适用于一对多,也就是监听的属性影响多个属性,例如搜索框搜索。
一、 具体解析
Vue 中的 computed 和 watch 都是用来监听数据变化并做出相应的操作,区别在于使用场景和功能上是有所不同。
1、功能上的区别
computed 是 计算属性
适用于需要根据已有的属性计算和处理,得出一个新值的场景;
watch 是 监听一个值的变化,然后执行对应的回调。
适用于需要对数据变化做出响应或者执行异步操作的场景。
2、是否调用缓存
computed 属性的值会被缓存,只有在依赖数据发生变化时才会重新计算,这样可以避免重复计算,提高性能。
如果所依赖的属性没有发生变化,那么调用当前的函数的时候会从缓存中读取;
而 watch 属性不会缓存计算结果,在每次监听的值发生变化的时候都会执行回调。
watch 属性可以监听单个数据或者一个数据数组,当数据发生变化时,watch 属性会执行对应的回调函数。
3、是否调用 return
computed 中的函数必须要用 return 返回;watch 中的函数不是必须要用 return。
4、第一次加载的时候是否开始监听
computed 默认第一次加载的时候就开始监听;
可以依赖于其他的响应式数据,当这些数据发生变化时,computed 属性会自动更新。
watch 默认第一次加载不做监听
如果需要第一次加载做监听,添加 immediate 属性,设置为 true(immediate:true)
5、使用场景的区别
当一个属性受多个属性影响的时候,使用 computed(一对多),例如购物车商品结算;
当一条数据影响多条数据的时候,使用 watch(多对一),例如搜索框。
二、在 Vue2 和 Vue3 的区别
Vue2 中有三种 watcher
渲染 watcher 、计算属性 watcher、 用户 watcher
Vue3 中有三种 effect
渲染 effect 、计算属性 effect、 用户 effect
1、computed
计算属性仅当用户取值时才会执行对应的方法;
computed 属性是具备缓存功能的;
多次执行的时候,底层会通过 dirty 变量来控制是否重新执行。
依赖的值变化了才会将 dirty 的值变为 true,为 true 的时候才会重新的去执行函数。
依赖的值不发生变化,对其取值时计算属性方法不会重新执行;
计算属性可以简化模板中复杂表达式;
计算属性中不支持异步逻辑,因为它要求同步返回结果;
计算属性是可以在模板中使用的;
① Vue2 的计算属性
每一个计算属性内部维护一个 dirty 属性, dirty: true
当取值的时候 dirty 为 true 就执行用户的方法,拿到值缓存起来,缓存在 this.value 中,并且将 dirty = false;
那再次取值的时候判断到 dirty 为 false,直接返回缓存的 this.value;
实现过程:
① 计算属性会创建一个计算属性 watcher,这个 watcher(lazy:true) 不会立刻执行;
② 通过 object.defineProperty 将计算属性定义到实例上;
③ 当用户取值时会触发 getter,拿到计算属性对应的 watcher,看 dirty 是否为 true,如果为true 则求值;
④ 并且让计算属性 watcher 中依赖的属性收集最外层的渲染 watcher,可以做到依赖的属性变化了,触发计算属性更新 dirty 并且可以触发页面更新;
⑤ 如果依赖的值没有发生变化,则采用缓存。
② Vue3 的计算属性
和 Vue2 不一样的是,这个计算属性会收集当前组件渲染产生的 effect;
依赖的值变化后,会通知计算属性 effect 更新 dirty,并且计算属性会触发自己收集的渲染 effect 执行。
2、watch
watch 则是监控值的变化,当值发生变化时调用对应的回调函数;
经常用于监控某个值的变化,进行一些操作(异步要注意竞态问题)
Vue3 提供了 onCleanup 函数,让用户更加方便使用也解决了清理问题
三、总结
watch
:
- 用于监听特定数据的变化,并在数据变化时执行相应的操作;
- 可以监听某个数据的变化,也可以监听多个数据的变化;
- 适合处理异步操作或复杂的数据变化逻辑;
- 通过
watch
监听的数据发生变化时,可以执行一些异步操作、复杂逻辑计算或手动操作DOM 等;
computed
:
computed
用于基于响应式依赖进行动态计算,并返回计算结果。- 依赖于响应式数据,只有当依赖的数据发生改变时,
computed
才会重新计算。- 适合进行简单的数据计算、筛选、排序等操作。
- 由于
computed
是基于依赖缓存的,可以有效减少不必要的计算,提高性能。
总的来说,computed 属性适用于基于响应式数据进行计算和处理的场景,而 watch 属性适用于监听数据变化并执行一些异步、复杂逻辑操作的场景。
当需要根据已有数据计算一个新值时,使用 computed 属性可以提高性能。
而当需要监听数据变化并执行一些逻辑时,使用 watch 属性可以更加灵活和方便。
我们需要根据具体的业务场景选择合适的方式来监听数据变化并做出相应的处理。