精通vue3 - 快速掌握ref和reactive

49 阅读4分钟

ref 和 reactive区别

在 Vue 3 中, refreactive 是用于创建响应式数据的两种方式,它们有一些区别和原理。

  1. 区别:

    • refref 函数用于创建一个包装后的响应式引用对象。它返回一个具有 .value 属性的对象,该属性包含实际的值。当访问或修改 ref 对象时,需要使用 .value 属性。例如: const count = ref(0); console.log(count.value);
    • reactivereactive 函数用于创建一个响应式代理对象。它接收一个普通的 JavaScript 对象,并返回一个代理对象。通过代理对象访问属性时,会自动追踪属性的依赖关系。例如: const state = reactive({ count: 0 }); console.log(state.count);
  2. 原理:

    • refref 函数会将传入的值包装成一个响应式引用对象。当访问引用对象时,会返回 .value 属性的值。当修改引用对象时,会触发更新通知,使得相关的组件重新渲染。
    • reactivereactive 函数会使用 JavaScript 的 Proxy 对象创建一个响应式代理对象。通过代理对象访问属性时,会触发 getter 和 setter,从而追踪属性的依赖关系。当属性被修改时,会触发更新通知,使得相关的组件重新渲染。

总的来说, refreactive 都可以用于创建响应式数据,但在使用方式和语义上有一些区别。 ref 适用于创建单个值的响应式数据,而 reactive 适用于创建包含多个属性的响应式对象。

ref的原理及其简化源码

ref 函数是 Vue 3 中用于创建响应式引用对象的函数。它的原理是通过创建一个包装对象来实现响应式。

以下是 ref 函数的大致源码示例:

function ref(value) {
  // 创建一个响应式对象
  const obj = {
    value: value
  };

  // 为 value 属性创建 getter 和 setter
  Object.defineProperty(obj, 'value', {
    get() {
      // 在 getter 中追踪依赖
      track(obj, 'value');
      return value;
    },
    set(newValue) {
      if (newValue !== value) {
        // 更新值
        value = newValue;
        // 触发更新
        trigger(obj, 'value');
      }
    }
  });

  return obj;
}

在上面的源码示例中, ref 函数接收一个初始值,并创建一个包含 value 属性的对象。通过 Object.defineProperty 方法,为 value 属性创建了一个 getter 和 setter。在 getter 中,会调用 track 函数来追踪依赖,确保在属性被访问时能够收集相关的依赖。在 setter 中,如果新值与旧值不相等,会更新值并触发更新,调用 trigger 函数通知相关的依赖进行更新。

通过这种方式, ref 函数创建的对象就具有了响应式的特性,当 value 属性被访问或修改时,会自动触发相关的依赖更新。

需要注意的是,以上源码示例只是简化的示例,实际的 Vue 3 源码中还有更多的细节和处理逻辑。如果您对 Vue 3 的源码感兴趣,建议查阅 Vue 3 的官方源码仓库。

ref的原理及其简化源码

reactive 函数是 Vue 3 中用于创建响应式代理对象的函数。它的原理是通过使用 JavaScript 的 Proxy 对象来实现响应式。

以下是 reactive 函数的大致源码示例(部分简化):

function reactive(obj) {
  // 创建一个响应式代理对象
  const observed = new Proxy(obj, {
    get(target, key, receiver) {
      const value = Reflect.get(target, key, receiver);
      // 在 getter 中追踪依赖
      track(target, key);
      return isObject(value) ? reactive(value) : value;
    },
    set(target, key, value, receiver) {
      const oldValue = Reflect.get(target, key, receiver);
      const result = Reflect.set(target, key, value, receiver);
      if (result && oldValue !== value) {
        // 触发更新
        trigger(target, key);
      }
      return result;
    },
    // 其他针对 deleteProperty、has 等操作的处理
  });

  return observed;
}

在上面的源码示例中, reactive 函数接收一个普通的 JavaScript 对象 obj ,并使用 Proxy 对象创建了一个响应式代理对象 observed 。通过代理对象的 getter 和 setter,实现了对属性的拦截和追踪。

在 getter 中,通过 Reflect.get 获取属性值,并在追踪依赖后返回。如果属性值是对象,会递归调用 reactive 函数,将其转换为响应式对象。

在 setter 中,通过 Reflect.set 设置属性值,并在新值与旧值不相等时触发更新,调用 trigger 函数通知相关的依赖进行更新。

通过这种方式, reactive 函数创建的对象就具有了响应式的特性,当属性被访问或修改时,会自动触发相关的依赖更新。

需要注意的是,以上源码示例只是简化的示例,实际的 Vue 3 源码中还有更多的细节和处理逻辑。如果您对 Vue 3 的源码感兴趣,建议查阅 Vue 3 的官方源码仓库。