Vue 3 中 reactive 与 ref 的区别与实践

在 Vue 3 中,reactiveref 是两种常用的响应式数据声明方式。但在实际开发中,我们常会遇到一个问题:明明对象的属性值发生变化了,界面却没有更新

本文将通过实际代码问题来分析原因,并给出最佳实践。

一、常见问题示例

以下代码使用了 reactive 创建响应式对象:

const dataObj = reactive({
  data: [],
  total: 0
})

http.post('/api/trade/bargain_detail_list', params).then(res => {
  const { data } = res
  dataObj.data = data
  dataObj.total = data.length
})

乍看之下没问题,但你会发现页面没有更新数据。为什么?

二、问题分析

reactive 是基于 Proxy 实现的深层响应式代理,它能追踪对象属性的读取与设置。然而:

如果组件并没有显式使用某个属性,Vue 就不会建立对它的响应式依赖。

例如组件内部只读取了一次 dataObj,而不是 dataObj.data,那即使你改了 dataObj.data,也不会触发更新。

而使用 ref 就不会出现这种问题:

const dataObj = ref({
  data: [],
  total: 0
})

// 替换整个对象,页面响应更新
dataObj.value = {
  ...dataObj.value,
  data: res.data,
  total: res.data.length
}

这种方式 Vue 能检测到整个对象变化,依赖会被更新。

三、推荐解决方案

方案 1:使用 ref 包裹对象

const dataObj = ref({
  data: [],
  total: 0
})

dataObj.value.data = res.data
dataObj.value.total = res.data.length

方案 2:使用 reactive,但操作内部属性需谨慎

避免整体替换属性,推荐使用数组变更方法:

dataObj.data.splice(0, dataObj.data.length, ...res.data)

这样可以保留数组的响应式引用,触发组件更新。

四、何时用 reactive?何时用 ref?

场景 推荐
定义一个简单的基本类型(如 string, number) ref
定义一个对象但需要替换整体数据 ref
定义一个结构稳定的复杂对象,并不替换它本身 reactive

五、总结

  • reactive 是深层响应,但不能整体替换属性对象,否则可能不更新。
  • ref 包裹对象后使用 .value 可整体替换并触发响应。
  • 推荐在异步数据赋值中使用 ref + 替换整个对象。

掌握好这两者的差异与用法,能让你的 Vue 3 项目响应更流畅,逻辑更清晰。

发表回复