Vue3中ref与reactive有什么区别

发布时间:2021-10-25 10:33:31 作者:iii
来源:亿速云 阅读:268
# Vue3中ref与reactive有什么区别

## 引言

在Vue3的Composition API中,`ref`和`reactive`是两个最常用的响应式API。虽然它们都能实现数据的响应式更新,但在使用场景、实现原理和细节处理上存在显著差异。本文将深入分析二者的区别,帮助开发者做出合理选择。

---

## 核心区别概览

| 特性                | ref                          | reactive                  |
|---------------------|------------------------------|---------------------------|
| **数据类型**        | 基本类型/对象                | 仅对象                   |
| **访问方式**        | 需通过`.value`访问           | 直接访问                 |
| **TS类型支持**      | Ref<T>                       | 无额外类型包装           |
| **解构响应性**      | 保持响应性                   | 失去响应性               |
| **原理实现**        | 对象包装 + Proxy             | 直接Proxy代理             |
| **适用场景**        | 独立变量/组件状态            | 复杂对象/嵌套数据结构    |

---

## 一、基本定义与用法

### 1. ref
```javascript
import { ref } from 'vue'
const count = ref(0) // 包装基本类型
const user = ref({ name: 'Alice' }) // 也可包装对象

// 访问需使用.value
console.log(count.value) // 0
count.value++

特点: - 可接受任何类型的值 - 返回一个带有value属性的响应式对象 - 模板中自动解包(无需.value

2. reactive

import { reactive } from 'vue'
const state = reactive({
  count: 0,
  user: { name: 'Alice' }
})

// 直接访问属性
console.log(state.count) // 0
state.count++

特点: - 只接受对象类型 - 返回原始对象的Proxy代理 - 嵌套属性自动转为响应式


二、实现原理对比

ref的底层机制

// 伪代码实现
function ref(value) {
  return {
    get value() {
      track() // 依赖收集
      return value
    },
    set value(newVal) {
      value = newVal
      trigger() // 触发更新
    }
  }
}

当值为对象时,内部会调用reactive进行转换

reactive的Proxy实现

const reactive = (target) => new Proxy(target, {
  get(target, key, receiver) {
    track(target, key)
    return Reflect.get(...arguments)
  },
  set(target, key, value, receiver) {
    Reflect.set(...arguments)
    trigger(target, key)
  }
})

三、关键差异详解

1. 响应性丢失问题

reactive的解构陷阱

const state = reactive({ x: 1, y: 2 })
// 解构后失去响应性!
const { x, y } = state

ref的解构优势

const pos = ref({ x: 1, y: 2 })
// 保持响应性
const { x, y } = pos.value

解决方案:使用toRefs转换

> const state = reactive({ x: 1 })
> const { x } = toRefs(state) // 现在x是ref
> ```

### 2. 类型系统表现
**ref的类型提示**:
```typescript
const count = ref<number>(0) // Ref<number>
count.value = "1" // TS报错

reactive的类型限制

interface State {
  foo: string
  bar?: number
}
const state: State = reactive({ foo: 'hi' })

3. 性能考量


四、最佳实践建议

推荐使用ref的场景

  1. 基础类型数据(string/number/boolean)
  2. 需要频繁重新赋值的变量
  3. 需要作为props传递的响应式值
  4. 需要保持响应性的解构操作

推荐使用reactive的场景

  1. 表单对象等复杂数据结构
  2. 需要深度监听嵌套属性的场景
  3. 相关状态需要逻辑聚合时
    
    const form = reactive({
     username: '',
     password: '',
     rules: {...}
    })
    

混合使用模式

const loading = ref(false)
const pagination = reactive({
  page: 1,
  pageSize: 10
})

五、常见问题解答

Q1:为什么ref需要.value而reactive不需要?
A1:ref通过对象包装实现基本类型的响应式,而reactive直接代理原始对象。

Q2:能否用ref代替所有reactive?
A2:技术上可行,但会导致代码中大量.value,降低可读性。

Q3:如何选择watch监听方式?
- 监听ref:watch(count, (val) => {...})
- 监听reactive属性:watch(() => state.foo, (val) => {...})


总结

决策因素 选择ref 选择reactive
数据类型 基本类型/简单对象 复杂嵌套对象
访问便利性 接受.value操作 希望直接访问
代码组织 分散的状态 逻辑相关的状态聚合

理解二者的差异后,开发者可以根据具体场景灵活选择。Vue3官方推荐:能用reactive优先使用,简单值用ref,这种组合方式往往能获得最佳开发体验。 “`

推荐阅读:
  1. Vue中Ref与Reactive的区别是什么
  2. 怎么在vue3中使用setup、 ref、reactive

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue ref reactive

上一篇:什么是MYSQL的开发思路

下一篇:Python爬虫经常会被封的原因是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》