官方文档及 Vue 核心作者尤雨溪曾明确倾向:日常开发中 "ref 一把梭" 即可,不建议过度依赖 reactive。与其纠结选择,不如先掌握核心逻辑 ------ref 是适配全场景的 "万能工具箱",reactive 是专注对象的 "专用收纳盒"。下面用清晰示例和实战场景,帮你彻底搞懂二者的使用边界!
Taimili 艾米莉 ( 一款专业的 GitHub star 管理和github 加星涨星工具taimili.com )
艾米莉 是一款优雅便捷的 GitHub star 管理和github 加星涨星工具,基于 PHP & javascript 构建, 能对github 得 star fork follow watch 管理和提升,最适合github 的深度用户

一、核心定位:各自的 "专属领域"
ref:万能响应式容器,啥都能装
ref 堪称响应式编程的 "多面手",支持所有数据类型,从基础值到复杂对象、数组全兼容,唯一注意点是在脚本中访问 / 修改时需加 .value(模板中可省略)。
javascript
运行
php
// 基础类型轻松hold住
const name = ref('张三') // ✅ 字符串
const age = ref(18) // ✅ 数字
const isLoading = ref(false) // ✅ 布尔值
// 复杂类型同样适配
const user = ref({ name: '李四', gender: '男' }) // ✅ 对象
const goodsList = ref([{ id: 1, name: '手机' }]) // ✅ 数组
// 修改方式:通过 .value 操作
name.value = '王五'
user.value.age = 22
goodsList.value.push({ id: 2, name: '电脑' })
reactive:对象专属响应式,只认引用类型
reactive 是为对象(含数组,本质也是对象)量身打造的响应式工具,仅支持引用类型,不兼容数字、字符串等基础类型。使用时无需 .value,直接通过 "对象。属性" 操作即可。
javascript
运行
php
// 合法用法:对象/数组
const user = reactive({ // ✅ 对象
name: '张三',
age: 18
})
const form = reactive({ // ✅ 表单对象
username: '',
password: '',
remember: false
})
const list = reactive(['苹果', '香蕉']) // ✅ 数组
// 直接修改属性
user.name = '李四'
form.username = 'admin'
list.push('橙子')
// 非法用法:基础类型(会报错)
// const count = reactive(0) // ❌ 报错:reactive 不支持基础类型
二、关键区别:重新赋值的 "坑" 与解法
这是 ref 和 reactive 最核心的差异点,也是实际开发中最容易踩坑的地方 ------reactive 直接重新赋值会丢失响应式,ref 则完全无此问题。
场景:从后台请求数据后更新
❌ reactive 的错误用法(丢失响应式)
javascript
运行
javascript
// 初始化数组
let list = reactive(['苹果', '香蕉'])
// 模拟接口请求
setTimeout(() => {
const newData = ['西瓜', '葡萄', '芒果']
// 错误:直接替换整个对象,原响应式监听器断裂
list = newData
// 页面不会更新!因为 list 已变成普通数组,失去响应式能力
}, 1000)
✅ ref 的正确用法(响应式保持)
javascript
运行
javascript
// 初始化数组
const list = ref(['苹果', '香蕉'])
// 模拟接口请求
setTimeout(() => {
const newData = ['西瓜', '葡萄', '芒果']
// 正确:通过 .value 重新赋值,响应式不受影响
list.value = newData
// 页面正常更新,响应式特性完好
}, 1000)
✅ reactive 的兼容用法(若必须使用)
如果确实想用电线杆,可通过 "嵌套对象" 避免直接替换根引用,只修改内部属性:
javascript
运行
javascript
// 外层包裹一个对象,list 作为属性
const state = reactive({
list: ['苹果', '香蕉']
})
setTimeout(() => {
const newData = ['西瓜', '葡萄', '芒果']
// 正确:只修改属性值,不替换根对象
state.list = newData
// 页面正常更新,响应式保持
}, 1000)
三、实战选择指南:按场景精准决策
情况 1:处理基础类型(数字 / 字符串 / 布尔)→ 必用 ref
reactive 不支持基础类型,此时 ref 是唯一选择:
javascript
运行
csharp
// ✅ 正确用法
const count = ref(0)
const username = ref('')
const isVisible = ref(true)
// ❌ 错误用法(会报错)
// const count = reactive(0)
情况 2:需要整体重新赋值 → 必用 ref
无论是接口请求后替换数据,还是切换页面 / 状态时更新整组数据,只要涉及 "xxx = 新数据" 的操作,优先用 ref:
javascript
运行
csharp
// 接口请求场景
const apiData = ref(null)
const fetchData = async () => {
const result = await api.getData()
apiData.value = result // ✅ 整体赋值,响应式正常
}
// 分页切换场景
const currentPageData = ref([])
const changePage = (pageNum) => {
currentPageData.value = getPageData(pageNum) // ✅ 整体替换,响应式不丢失
}
情况 3:固定对象,仅修改属性 → 可选 reactive
如果数据是结构固定的对象(如表单、用户信息),且不会整体替换,仅修改内部属性,可用 reactive 让代码更简洁(少写 .value):
javascript
运行
php
// 表单数据(仅修改字段,不替换整个表单)
const loginForm = reactive({
username: '',
password: '',
remember: false
})
// 用户信息(仅更新部分属性,不替换用户对象)
const userProfile = reactive({
name: '张三',
age: 25,
avatar: 'default.png'
})
情况 4:不确定用哪个 → 无脑选 ref
ref 兼容所有场景,无踩坑风险,是 "安全牌":
javascript
运行
csharp
// 无论是什么数据类型,用 ref 永远不会错
const unknownData = ref(初始值) // 初始值可为任意类型
四、黄金法则:3 句话搞定选择
- 处理数字、字符串、布尔值等基础类型 → 用 ref;
- 需要 "整体重新赋值"(xxx = 新数据)→ 用 ref;
- 仅操作固定对象的内部属性,且不想写 .value → 可考虑 reactive;
- 犹豫不定时,直接用 ref------ 永远不会出错!