返回

揭秘Vue.js核心:Computed与Watch,你一定不能错过的源码分析

前端

Computed与Watch:Vue.js中的双雄争霸

深入浅出,揭秘响应式编程的神秘面纱

在Vue.js的浩瀚世界中,Computed和Watch可谓是两颗璀璨的明珠,它们让响应式编程变得优雅而高效。然而,这两者看似相近,实则各具妙用,本文将深入浅出地剖析它们的本质区别,带你领略Vue.js的核心奥秘。

Computed:依赖的舞者

Computed是一个计算属性,它依赖于其他属性的值而存在。当这些依赖项发生改变时,Computed的值也会随之更新。就像一个舞蹈演员,它时刻关注着音乐的变化,当旋律变幻时,它的舞姿也随之而变。

Watch:敏锐的守望者

与Computed不同,Watch是一个侦听器。它监视某个属性或表达式的变化,一旦侦测到变化,就会执行指定的回调函数。就像一个守望者,它时刻警惕着目标对象的动态,一旦有风吹草动,它便会拉响警报。

三种形态,各显神通

Computed和Watch都有三种不同的形态,分别适用于不同的场景:

1. 计算属性Computed

语法糖:computed。依赖其他属性的值,当依赖项发生变化时,自动重新计算。

优点:性能优异,仅在依赖项改变时才会重新计算。

缺点:只能访问响应式数据。

2. 侦听器user watcher

语法糖:watch。监听某个属性或表达式的变化,当变化发生时,触发指定的回调函数。

优点:可以访问响应式数据和非响应式数据。

缺点:性能开销较大,每次组件重新渲染时都会执行回调函数。

3. 渲染watcher

语法糖:renderWatch。一个特殊的Watch,专门用于监听组件的渲染函数。

优点:可以访问组件的渲染函数,方便性能优化。

缺点:只能用于组件的渲染函数。

应用场景:量体裁衣

Computed和Watch各有千秋,适用于不同的场景:

使用Computed: 当需要一个依赖于其他属性的值的计算属性时。

使用Watch: 当需要监听某个属性或表达式的变化时。

深入解读:源码探秘

为了更深入地理解Computed和Watch,让我们深入Vue.js的源码一探究竟。

Computed:

export function computed(getterOrOptions, context) {
  // 解析 getterOrOptions
  let getter;
  let setter;

  if (typeof getterOrOptions === 'function') {
    getter = getterOrOptions;
  } else {
    // getter 和 setter 函数
    getter = getterOrOptions.get || function () {};
    setter = getterOrOptions.set || function () {};
  }

  // 创建依赖追踪器
  const watcher = new Watcher(
    context,
    getter,
    undefined, // computed 不支持 setter
    { lazy: true } // computed 默认惰性求值
  );

  // getter 依赖的属性发生变化时,会触发 watcher
  // 进而更新 computed 的值

  return {
    get() {
      // 获取 computed 的值
      // 如果是惰性求值,则首次获取时计算
      if (watcher.dirty) {
        watcher.evaluate();
      }

      if (Dep.target) {
        // 如果有订阅者(比如模板),则收集依赖
        watcher.depend();
      }

      return watcher.value;
    },
    set(newValue) {
      // 理论上 computed 应该是只读的,但还是提供了 setter
      // 可以用于手动更新 computed 的值
      setter.call(context, newValue);
      watcher.evaluate();
    }
  };
}

Watch:

export function watch(expOrFn, callback, options) {
  const watcher = new Watcher(
    this,
    expOrFn, // 表达式或函数
    callback, // 回调函数
    options // 选项
  );

  // 添加到组件的 watcher 数组中
  if (this._watchers.length === 0) {
    this._isVue = true;
  }
  this._watchers.push(watcher);
}

性能优化:巧用利器

Computed和Watch都可以用于性能优化:

Computed: 减少不必要的重新渲染。

Watch: 避免不必要的回调函数执行。

结束语:登峰造极

Computed和Watch是Vue.js响应式编程的基石。理解它们的本质区别和应用场景至关重要。掌握了这些利器,你将能够轻松编写出响应迅速、性能卓越的Vue.js应用。

常见问题解答

Q:Computed和Watch哪个性能更好?

A:Computed通常性能更好,因为它只在依赖项发生变化时才会重新计算。

Q:什么时候应该使用Watch,而不是Computed?

A:当需要监听某个属性或表达式的变化,并且该变化不影响组件渲染时,可以使用Watch。

Q:Computed可以访问非响应式数据吗?

A:不可以,Computed只能访问响应式数据。

Q:Watch可以触发重新渲染吗?

A:可以,如果Watch的回调函数修改了响应式数据,就会触发重新渲染。

Q:如何优化Watch的性能?

A:可以使用immediate选项来避免在初始化时触发回调函数,还可以使用deep选项来避免深度观察数组和对象。