Vue3中定义变量是选择ref还是reactive?

Ref 与reactive

在 Vue 3 中,reactive 和 ref 是用于创建响应式数据的两个不同的 API。它们都是 Vue 3 Composition API 的一部分。

ref:

ref 用于创建一个包装基本数据类型的响应式对象。它接受一个初始值,并返回一个包含 value 属性的对象。ref 主要用于包装基本数据类型,如数字、字符串等。

javascript 复制代码
import { ref } from 'vue';

const count = ref(0);

// 读取值
console.log(count.value); // 输出: 0

// 修改值
count.value += 1;
console.log(count.value); // 输出: 1

reactive:

reactive 用于创建一个包装普通对象的响应式对象。它接受一个普通对象,并返回一个代理对象,该代理对象中的属性都是响应式的。

javascript 复制代码
import { reactive } from 'vue';

const user = reactive({
  name: 'John',
  age: 30,
});

// 读取值
console.log(user.name); // 输出: John

// 修改值
user.age += 1;
console.log(user.age); // 输出: 31

区别:

  1. 数据类型:

    • ref 主要用于包装基本数据类型,如数字、字符串等。
    • reactive 主要用于包装普通对象。
  2. 访问属性:

    • 在 ref 中,你需要通过 .value 访问和修改值。
    • 在 reactive 中,直接访问和修改对象的属性即可。
  3. 用例:

    • ref 通常用于单一值,如计数器、标志等。
    • reactive 通常用于包装对象,用于表示具有多个属性的数据。
javascript 复制代码
import { ref, reactive } from 'vue';

// 使用 ref
const count = ref(0);
count.value += 1;

// 使用 reactive
const user = reactive({
  name: 'John',
  age: 30,
});
user.age += 1;

为什么同时存在 ref()、reactive()?

ref 和 reactive 虽然都用于创建响应式对象,但它们在设计和用途上有一些区别,适用于不同的场景。理解这些差异有助于更好地选择合适的 API。

  1. 单一值 vs. 对象:

    • ref 主要用于包装基本数据类型,如数字、字符串等,以及需要单一值的情况。
    • reactive 用于包装普通对象,对于需要表示多个属性的数据结构。
    javascript 复制代码
    const count = ref(0); // 单一值
    const user = reactive({ name: 'John', age: 30 }); // 对象
  2. 访问方式:

    • 在 ref 中,你需要通过 .value 访问和修改值。
    • 在 reactive 中,直接访问和修改对象的属性即可。
    javascript 复制代码
    // 使用 ref
    count.value += 1;
    
    // 使用 reactive
    user.age += 1;
  3. 响应式原理:

    • ref 通过 Vue 3 提供的 ref 函数实现,它为基本数据类型提供了轻量级的响应式封装。
    • reactive 通过 Vue 3 提供的 reactive 函数实现,它使用 Proxy 对象来实现对整个对象的深层次响应式封装。
  4. 用例和场景:

    • ref 适用于简单的值或在模板中需要直接使用的值。
    • reactive 适用于表示复杂数据结构,需要处理多个属性的情况,尤其是在逻辑层面需要进行深层次的数据操作时。
javascript 复制代码
import { ref, reactive } from 'vue';

// 使用 ref
const count = ref(0);
count.value += 1;

// 使用 reactive
const user = reactive({ name: 'John', age: 30 });
user.age += 1;

虽然在某些简单的场景中使用 ref 就足够了,但当处理更复杂的数据结构时,尤其是需要进行深层次的数据操作时,reactive 提供了更强大的功能。选择使用哪个 API 取决于你的具体需求和项目的复杂性。

ref与普通变量的区别

ref 在 Vue 3 的 Composition API 中被引入,它主要用于创建响应式对象,尤其是用于包装基本数据类型的响应式对象。相比于普通变量,ref 具有一些特别的支持和行为:

  1. 响应式变化检测:

    • ref 创建的对象是响应式的,意味着当其值发生变化时,相关的视图会进行更新。
    • 普通变量在 Vue 2 中没有内置的响应式支持,需要使用 Object.defineProperty 或 Vue.set 手动进行响应式处理。
  2. .value 访问和修改:

    • 在使用 ref 创建的响应式对象中,需要通过 .value 访问和修改值。

    • 这是因为 ref 的设计初衷是为了确保在模板中使用变量时能够区分变量本身和它的值。因此,直接操作 ref 对象会导致一些问题,必须使用 .value。

      javascript 复制代码
      const count = ref(0);
      console.log(count.value); // 读取值
      count.value += 1; // 修改值
  3. 自动解包:

    • 在模板中使用 ref 变量时,Vue 3 会自动解包,直接访问变量值,而不需要显式使用 .value。

    • 这样可以在模板中获得更自然的语法。

      html 复制代码
      <!-- 在模板中自动解包 -->
      <template>
        <div>{{ count }}</div>
      </template>
  4. ref 函数:

    • ref 函数是 Vue 3 提供的 API,用于创建一个包装基本数据类型的响应式对象。这个函数的使用方式使得 Vue 能够更轻松地追踪数据的变化。
    • 普通变量在 Vue 2 中不具备这种直接的响应式支持,需要额外的处理来使其响应式。

注意

在 Vue 3 中当你将 ref 对象传递到模板(<template>)中时,会自动解包,无需额外使用 .value。这是 Vue 3 的一个改进,旨在提供更自然的语法。

以下是一个示例,演示了在模板中传递和使用 ref 对象的情况:

html 复制代码
<!-- ParentComponent.vue -->
<template>
  <div>
    <p>Parent Component: {{ myRef }}</p>
    <ChildComponent :childRef="myRef" />
  </div>
</template>

<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent,
  },
  setup() {
    const myRef = ref('Hello from Parent');
    return {
      myRef,
    };
  },
};
</script>
html 复制代码
<!-- ChildComponent.vue -->
<template>
  <div>
    <p>Child Component: {{ childRef }}</p>
    <button @click="updateValue">Update in Child</button>
  </div>
</template>

<script>
import { defineComponent } from 'vue';

export default defineComponent({
  props: {
    childRef: {
      type: Object,
      required: true,
    },
  },
  methods: {
    updateValue() {
      // 在子组件中通过 .value 修改值
      this.childRef.value = 'Updated in Child';
    },
  },
});
</script>
相关推荐
卸任6 小时前
Vibe coding工具使用心得
前端·ai编程
brien97 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance7 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M7 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写7 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李7 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易7 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding8 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马8 小时前
前沿视界
前端
kyriewen8 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员