# Vue 3 响应式 API 深入解析：reactive、ref、toRef、toRefs

URL: https://caijiao.org/posts/3
Source: docs/posts/3.md
Description: 系统讲解 Vue 3 中 reactive、ref、toRef、toRefs 的区别、使用场景以及常见错误示例，帮助开发者更好理解响应式原理。

Vue 3 提供了丰富的响应式 API，让状态管理更加灵活。本文介绍四个核心 API：`reactive`、`ref`、`toRef`、`toRefs`，重点分析 **区别、使用场景**，并给出常见错误示例。

## 1️⃣ reactive

- **作用**：将对象或数组转换为响应式对象（深层响应式）。
- **适用场景**：
  - 对象或数组需要整体响应式
  - 包含嵌套对象或数组，修改内部属性也希望触发更新
- **特点**：
  - 返回一个 **Proxy**
  - 深层响应式
  - 不适合基本类型（number、string、boolean）

**正确示例**：

```js
import { reactive } from 'vue'

const state = reactive({
  count: 0,
  info: { name: 'Alice' }
})

state.count++           // 响应式更新
state.info.name = 'Bob' // 深层响应式
````

**错误示例**（对基本类型无效）：

```js
const count = reactive(0) // ❌ 不会成为响应式
```

## 2️⃣ ref

- **作用**：为基本类型或对象创建响应式引用
- **适用场景**：

  - 基本类型（number、string、boolean）
  - 对象也可用 ref 包裹，但内部对象不是深层响应式（除非用 reactive 包裹）
- **访问/修改**：通过 `.value`

**正确示例**：

```js
import { ref, reactive } from 'vue'

const count = ref(0)
count.value++       // 响应式更新

const obj = ref({ name: 'Alice' })
obj.value.name = 'Bob'  // 对象内部也可修改
```

**错误示例**（解构后失去响应式）：

```js
const obj = ref({ name: 'Alice' })
const { name } = obj.value
name = 'Bob'          // ❌ 不会触发响应式更新
```

## 3️⃣ toRef

- **作用**：将响应式对象的单个属性转换为 ref
- **适用场景**：

  - 需要单独解构对象的某个属性，同时保持响应式
- **特点**：

  - 修改 ref.value 会同步到原对象
  - 避免响应式丢失问题

**正确示例**：

```js
import { reactive, toRef } from 'vue'

const state = reactive({ count: 0 })
const countRef = toRef(state, 'count')

countRef.value++       // state.count 同步更新
```

**错误示例**（直接解构属性）：

```js
const { count } = state   // ❌ count 不是 ref，解构后丢失响应式
count++                   // 不会更新 state.count
```

## 4️⃣ toRefs

- **作用**：将响应式对象的所有属性都转换为 ref，返回对象
- **适用场景**：

  - 解构对象后仍希望保持响应式
- **特点**：

  - 每个属性变成 ref
  - 修改 ref.value 会同步到原对象

**正确示例**：

```js
import { reactive, toRefs } from 'vue'

const state = reactive({ count: 0, name: 'Alice' })
const { count, name } = toRefs(state)

count.value++        // state.count 同步更新
name.value = 'Bob'   // state.name 同步更新
```

**错误示例**（解构 reactive 对象直接赋值）：

```js
const { count, name } = state   // ❌ 不使用 toRefs
count++                         // 不会触发响应式
```

## 5️⃣ 区别与总结

| API      | 适用类型    | 响应式深度 | 解构安全 | 使用场景            |
| -------- | ------- | ----- | ---- | --------------- |
| reactive | 对象/数组   | 深层    | ❌    | 整体对象响应式，嵌套属性响应  |
| ref      | 基本类型/对象 | 单层    | ❌    | 单值响应式，基本类型或对象引用 |
| toRef    | 对象单个属性  | 单层    | ✅    | 解构单个属性仍保持响应式    |
| toRefs   | 对象所有属性  | 单层    | ✅    | 解构对象后仍保持所有属性响应式 |

## ✅ 小结

1. **reactive**：对象/数组整体响应式
2. **ref**：基本类型或单个对象引用
3. **toRef**：单个属性解构安全
4. **toRefs**：多个属性解构安全


基本类型一定要用 `ref`，不能直接用 `reactive`。  
使用不当（解构 reactive 或 ref.value 内部对象）会丢失响应式。
