面试被问 computed 和 watch 的区别,这样回答够了吗?

855 阅读2分钟

对于 computed 函数首先要明白一个概念:

Vue 会在内部为 compouted 函数创建一个只有 value 值的对象。这个对象可以被称作响应式对象,value 值的 get 函数会执行 compouted 函数并缓存其值,若当前是 render job、computed job、或者 watch job 阶段,还会将 value 与当前 job 绑定依赖关系,当 value 的值变更时,打开缓存控制变量,触发这些 job,这些 job 又触发执行 value 的 get 函数,重新计算 compouted 函数,并重新绑定依赖。

而 watch 是作为 job 来看的,将回调函数包装在一个 job 中,和响应式对象的属性值建立依赖关系。当响应式对象的属性值变更时,执行 job,也就会执行回调函数。watch 函数可以设置 immerdiate: true,在组件初始化阶段立即执行。

总结一下:

computed 既可依赖其他响应式对象,也可作为响应式对象被其他 job 依赖,比如 computed job、render job、watch job,且只有在被需要时,才会去执行,并会对计算值缓存。

watch 只可作为 job,依赖其他响应式对象属性。且可以设置立即执行。

当它们都作为 job 时,computed 可以依赖多个响应式对象的属性,而 watch 只可以依赖一个。

watch 有一些特性

  • 当 watch 设置为 immediate:true 时,其回调函数在组件初始化时,render job 之前就会执行。
  • 在 mounted 前,watch 是同步执行的。
  • 在 mounted 后,watch 是异步执行的,而且在 render job 之前执行。

computed 有一些特性

当响应式对象属性值变更时,其实会主动触发依赖 computed 函数内置对象的属性值 value 的 job,render job 和 watch job 是异步执行的,所以 comouted 函数也会异步执行。

举个例子:

假设当前是 render job,有 computed1 和 computed2 两个计算函数,有变量 x。

render job 依赖 compuetd1,computed1 依赖 computed2, computed2 依赖 x。

x 变更,触发执行 computed2 job,打开 computed2 的缓存开关,触发 computed1 job

computed1 job 执行,打开 computed1 的缓存开发,触发 render job

render job 执行,重新执行 computed1 计算函数,computed1 执行过程中又重新执行 computed2 计算函数。

所以其实 x 变更时, computed2 要比 computed1 先执行,而且是异步执行,因为 render job 是异步的。如果没有 render job,那么当 x 变更时因为没有 job 获取computed1,所以 computed1 计算函数和 computed2 计算函数都不会执行,除非我们手动获取 computed1 属性,可以同步触发 computed1 和 computed2 的执行。