【Vue代码分析】Vue响应式数据驱动视图(三):ref 和 computed 本质上是在做同一件事吗?

承接这两篇博客的分析:

【Vue代码分析】Vue响应式数据驱动视图(一):为什么直接赋值在 Vue 中会失效?https://blog.csdn.net/weixin_52047874/article/details/162634506?sharetype=blogdetail&sharerId=162634506&sharerefer=PC&sharesource=weixin_52047874&spm=1011.2480.3001.8118【Vue代码分析】Vue响应式数据驱动视图(二):为什么一个布尔值也要用 ref?https://blog.csdn.net/weixin_52047874/article/details/162635089?sharetype=blogdetail&sharerId=162635089&sharerefer=PC&sharesource=weixin_52047874&spm=1011.2480.3001.8118

在前两篇文章中,我们分别讨论了两个经典场景:

  1. 为什么列表数据要用 computed 派生?
  2. 为什么加载状态要用 ref 定义?

这时候,敏锐的开发者往往会把这两个问题放在一起思考:

"这俩东西看起来用法完全不同,computed 是自动算的,ref 是手动改的。它们背后的核心原因是一样的吗?"

这是一个直击 Vue 设计灵魂的问题。

答案是:宏观上,是的;微观上,不是。

它们就像一枚硬币的两面,虽然为了解决不同的技术痛点而存在,但归根结底,都在服务于同一个终极目标。

一、 宏观视角:殊途同归的"破壁者"

如果我们把镜头拉远,站在架构的高度看,ref 和 computed 确实在做同一件事:打破 JavaScript 静态逻辑与 Vue 动态视图之间的壁垒。

在原生 JavaScript 中,变量只是内存里的一个代号,DOM 只是浏览器里的一个元素树。这两者本来是老死不相往来的。

  • 当你写 let isLoading = true 时,JS 变了,但 DOM 不会变。
  • 当你写 const list = data.children 时,源头变了,但 list 不会变。

Vue 的响应式系统,本质上就是一个**"连接器"**。

  • ref 的作用 :把一个原始值(如 boolean)变成一个可观察对象,强行插入到 Vue 的管理系统中。
  • computed 的作用 :把一个计算逻辑变成一个可观察对象,也强行插入到 Vue 的管理系统中。

核心原因的一致性:

只要你的数据需要**"驱动视图"** ,你就不能使用普通的 JS 变量。你必须使用 ref 或 computed 把数据"注册"进 Vue 的响应式世界里。

如果没有它们,Vue 就成了一个瞎子,看不见数据的流动,也就无法更新页面。

二、 微观视角:解决相反的两个"痛点"

虽然目标一致(建立连接),但它们解决的问题却刚好是相反的。

1. ref 解决的是:"我变了,怎么通知别人?"

在 isLoading 的场景中,痛点在于通知的缺失。

javascript 复制代码
// 场景:异步加载
isLoading.value = true // 我变了,但我怎么告诉 <van-loading> 组件?

普通的变量赋值是"静默"的。ref 利用 ES6 的 Proxy 或者 getter/setter 劫持了 .value 的赋值操作。

  • 核心原理 :拦截修改。
  • 作用 :当你修改数据时,ref 会自动触发 trigger 函数,大喊一声:"数据变了!",从而触发视图更新。

一句话:ref 是为了解决【手动变更后的通知问题】。

2. computed 解决的是:"源头变了,我怎么知道?"

在 subCategoryList 的场景中,痛点在于自动更新的缺失。

javascript 复制代码
// 场景:二级列表
const subCategoryList = computed(() => categoryList[activeIndex].children)
// activeIndex 变了,subCategoryList 怎么知道要重新计算?

普通的变量赋值是"一次性"的。computed 内部建立了一个精密的依赖收集系统。

  • 核心原理 :依赖追踪。
  • 作用 :它会记录自己依赖于谁(activeIndex)。一旦依赖项变了,Vue 会反过来通知 computed:"你的源头变了,快重新执行函数计算!",计算出新值后,再触发视图更新。

一句话:computed 是为了解决【源头变更后的自动推导问题】。

三、 深层联系:computed 其实就是"高级版"的 ref

如果你去翻看 Vue 的源码,你会发现一个有趣的秘密:computed 返回的对象,本质上也是一个 ref。

更准确地说,computed 是一个**"只读的、带有自动更新功能的 ref"**。

我们可以这样理解它们的关系:

  1. 普通 ref:

    • 值是谁?是你手动塞进去的。
    • 什么时候变?你调用 .value = xxx 时才变。
    • *类比:一个存钱罐,你自己往里扔钱,扔完它就响了。*
  2. 计算 ref (computed):

    • 值是谁?是函数运行出来的。
    • 什么时候变?是依赖的数据变了,Vue 帮你往里扔新值,然后它响了。
    • 类比:一个带有传感器的显示屏,传感器检测到温度(依赖)变了,显示屏自动刷新数字。

所以,当你使用 computed 时,Vue 实际上是在背后帮你创建了一个隐藏的 ref,并帮你写好了一个 watchEffect 来自动更新它。

四、 总结:响应式系统的"双保险"

回到最初的问题:"ref 和 computed 核心原因一样吗?"

  • 一样,是因为它们都是 Vue 响应式系统的入口。没有它们,数据流就是断的,视图就不会动。
  • 不一样,是因为它们守卫着数据流的不同阶段 。
    • ref 守卫着写入端,确保你的修改能被看见。
    • computed 守卫着读取/计算端,确保数据的派生逻辑能被自动执行。

在 Vue 开发中,我们其实就是在不断地做两件事:

  1. 用 ref 定义状态(State)。
  2. 用 computed 定义衍生(Derived State)。

这就是数据驱动视图的完整闭环。

相关推荐
西安小哥11 分钟前
做 Agent 写到第三个小时,我开始给它算账
javascript
西安小哥19 分钟前
让大模型操作浏览器跑了两周,我发现瓶颈根本不在模型
javascript
FungLeo33 分钟前
成为全栈·Vue 管理后台篇·Vue Query:服务端数据缓存、query key与变更失效
vue.js·数据获取·前端缓存·前端状态管理·tanstack query·vue query
用户2986985301434 分钟前
用 Python 自动化把 JavaScript 代码转换为 Word 文档
javascript·python·api
学以智用38 分钟前
正则表达式完整参考手册(JavaScript 版,兼容绝大多数语言)
javascript
北城笑笑1 小时前
Vue 109 ,从零搭建 Vue3 + Electron 工程:生态、安全桥接与打包选型( Vue + Electron )
前端·javascript·vue.js·安全·electron·vue
Highcharts.js1 小时前
Highcharts智能数据分析平台Orbit 多语言配置技术文档
java·前端·javascript·highcharts·orbit·智能数据分析·设置文档
计算机毕设定制辅导-无忧学长3 小时前
《基于Spring Boot的迷游哈游戏综合服务平台的开发》
java·vue.js·spring boot·mysql·迷游哈游戏综合服务平台
非优秀程序员12 小时前
第07章 孙德良的阳谋|《互联网产品恩仇录》
javascript·后端
非优秀程序员12 小时前
第04章 邮箱大战,163 与 QQ 的暗战|《互联网产品恩仇录》
java·vue.js·架构