zxdfe / FE-Interview

Every step counts
34 stars 1 forks source link

第42题:Vue中computed和watch的区别?、 #43

Open zxdfe opened 2 years ago

zxdfe commented 2 years ago

computed计算属性,依赖于某个或者某些属性值,当依赖的数据发生变化的时候才会更新。

watch 侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。

大白话一点

1.如果一个数据依赖于其他数据,那么把这个数据设计为computed的

2.如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化

本质区别,源码层

  1. 本质上,computed和 watch都是 watcher实例, compued是一个lazy watcher; watch属于user watcher;
//core/observer/watcher.js
class Watcher{
  constructor(){
    this.deep = !!options.deep
    this.user = !!options.user // watch
    this.lazy = !!options.lazy  // computed watch
    this.sync = !!options.sync
  }
}
  1. computed是有缓存的, 由this.dirty 控制。
// watcher.js
update () {
    /* istanbul ignore else */
    if (this.lazy) {
        // 计算属性要更新
        this.dirty = true
    } else if (this.sync) {
        this.run()
    } else {
        // ! 开启异步队列,批量更新Watcher
        queueWatcher(this)
    }
}

一旦我们对计算属性依赖的数据做修改,则会触发 setter 过程,通知所有订阅它变化的 watcher 更新,执行 watcher.update() 方法

// core/instance/state.js
export function initState (vm: Component) {
  vm._watchers = []
  const opts = vm.$options
  if (opts.props) initProps(vm, opts.props)
  if (opts.methods) initMethods(vm, opts.methods)
  if (opts.data) {
    initData(vm)
  } else {
    observe(vm._data = {}, true /* asRootData */)
  }
  if (opts.computed) initComputed(vm, opts.computed)
  if (opts.watch && opts.watch !== nativeWatch) {
    initWatch(vm, opts.watch)
  }
}

Vue 的计算属性真的会缓存吗?