ref和reactive
在 Vue 3 中,ref
和 reactive
是响应式系统的两个核心 API。它们都用于创建响应式的数据对象,使得当数据变化时,视图也能自动更新。但使用上有区别,尤其在处理异步请求获取数据后赋值的场景时,更要注意。
一、ref
与 reactive
的区别和使用
✅ ref
是什么?
ref
用来创建基本类型(如数字、字符串、布尔值)或单个对象/数组的响应式引用。ref
返回的是一个带有.value
属性的对象。
示例:
⚠️:不管是基本类型还是对象、数组,用
ref
包装后,都必须通过.value
访问和修改。
✅ reactive
是什么?
reactive
用来创建对象类型的响应式数据(对象、数组、嵌套结构)。- 直接使用对象属性,不需要
.value
。
示例:
import { reactive } from 'vue'
const state = reactive({
count: 0,
user: {
name: 'Tom',
age: 20
}
})
state.count++ // 响应式更新
⚠️:
reactive
不能直接用于基本类型(数字、字符串等),必须是对象或数组。
二、数据请求后赋值的处理
在项目开发中,我们经常是请求接口后,动态获取数据赋值到响应式变量中。这就涉及初始化时是否要写出键值的问题。
✅ 是否要初始化属性?
✅ 建议初始化 至少写好结构,理由如下:
- 防止模板中访问 undefined 报错;
- 保持响应式引用一致;
- 避免 watch/computed 无法监听到新属性。
示例 1:使用 ref
初始化为对象
import { ref, onMounted } from 'vue'
const userInfo = ref({
name: '',
age: null,
gender: ''
})
onMounted(async () => {
const res = await fetchUserData()
userInfo.value = res.data
})
如果初始化为
{}
,也可以,但推荐提前写出结构,避免页面绑定时出现userInfo.value.name
报错。
示例 2:使用 reactive
初始化
import { reactive, onMounted } from 'vue'
const userInfo = reactive({
name: '',
age: null,
gender: ''
})
onMounted(async () => {
const res = await fetchUserData()
Object.assign(userInfo, res.data)
})
使用
Object.assign
替换响应式对象的属性值,而不是直接替换整个对象(这样会失去响应式)。
三、ref vs reactive 在请求后的赋值注意点
场景 | 使用 ref |
使用 reactive |
---|---|---|
基本类型 | ✅ 推荐 | ❌ 不适合 |
对象或数组 | ✅ 可以,但访问要 .value |
✅ 推荐使用 |
数据整体替换 | ✅ 直接替换 .value |
❌ 不要直接替换,用 Object.assign |
初始化 | 可以是空,但建议写结构 | 建议写结构,避免响应式失效 |
模板使用 | 需要 .value (除非通过 setup() return 解包) |
直接访问属性即可 |
四、模板中的使用区别
使用 ref
:
使用 reactive
:
⚠️ 当然,如果你在
setup()
里用return { userInfo }
,Vue 会自动对.value
进行“解包”,让模板里不需要加.value
。
五、总结建议
✅ 对象/数组数据建议用 reactive
:
- 初始化时尽量写出属性结构,避免 undefined;
- 赋值时使用
Object.assign
而不是整个对象替换。
✅ 基本类型或需整体替换对象/数组时用 ref
:
- 使用
.value
访问; - 可以整体替换
ref.value = xxx
。
如果你正在开发页面,有异步请求场景,我可以帮你写个具体 demo,对比两种写法。需要吗?