⚙️ 《响应式原理》— Vue 是怎么做到自动更新的?

🔍 Vue 响应式原理全解:Proxy、依赖追踪与视图更新是怎么协作的?

在 Vue3 中,最核心也最神奇的机制之一就是它的 响应式系统

它可以做到:

你只管改数据,界面自动变得和你想要的一样。

但这背后的"魔法",其实主要靠 三大机制 协同工作:

✅ JavaScript Proxy

✅ 依赖追踪(依赖收集)

✅ 数据变动 → 触发视图更新

我们逐一拆开讲,最后你会发现:Vue 的响应式其实并不神秘。


1️⃣ Proxy:给数据加一个"监听器"

Vue3 用 Proxy 替代了 Vue2 的 Object.defineProperty,能对任意对象的读取和设置行为进行拦截

👇 模拟实现:

js 复制代码
const state = new Proxy({ count: 0 }, {
  get(target, key) {
    console.log(`读取了属性:${key}`)
    return target[key]
  },
  set(target, key, value) {
    console.log(`设置了属性:${key} = ${value}`)
    target[key] = value
    // 通知依赖更新视图
    return true
  }
})

state.count     // 打印:读取了属性:count
state.count++   // 打印:设置了属性:count = 1

🧠 注释解析:

  • get() 拦截访问属性,比如模板中 {{ count }};
  • set() 拦截属性修改,比如执行 state.count++;
  • 在这两个钩子中,Vue 会插入自己的逻辑,追踪依赖并触发更新

🏷️ 类比一下:

把数据对象 state 想象成"仓库货架",每个属性是一个"货物"。

  • get() 是你伸手去拿货,Vue 就偷偷记下"你拿了哪个货物(依赖)";
  • set() 是你换了一个新货上去,Vue 就通知"所有拿过这个货的地方该更新了"。

2️⃣ 依赖追踪:谁用我,我就记住谁

每当模板或计算属性中访问响应式数据,Vue 会自动记录"谁用了这个变量"。

js 复制代码
<template>
  <p>{{ count }}</p>
</template>

➡️ Vue 会记录:"这个

标签使用了 count"。

✅ Vue 怎么知道是谁在访问?

因为在模板编译成渲染函数后,Vue 会在执行这些函数时设置一个全局"正在渲染谁"的标记,然后在 get() 被触发时,记录下这个依赖。

👉 比喻一下:

就像老师点名时偷偷做记录:

谁抬头听讲了,就记下来了。以后要发新通知,就通知这些认真听讲的同学。


3️⃣ 触发更新:数据一改,立刻广播

当你修改响应式数据时,例如:

js 复制代码
state.count++  // 或 count.value++

Vue 会在 set() 中查找有哪些地方依赖了这个属性,并重新执行相关渲染函数或计算属性,从而触发 DOM 更新。

✅ 整个流程串起来长这样:

js 复制代码
用户访问 count --> Proxy.get 拦截 --> Vue 记录依赖
用户修改 count --> Proxy.set 拦截 --> Vue 通知所有依赖:你要更新了!
  • 详细的流程如下图所示:

流程说明:

  1. 依赖收集阶段 (读操作)

    • 用户读取 count 时触发 Proxy 的 get 拦截
    • Vue 将当前执行的函数(如组件渲染函数)注册为依赖
    • 依赖关系存储在 Dep 依赖集合中
  2. 更新通知阶段 (写操作)

    • 用户修改 count 时触发 Proxy 的 set 拦截
    • Vue 从 Dep 中获取所有关联的依赖项
    • 通知所有依赖项(如组件、计算属性)执行更新
    • 最终触发 UI 重新渲染或计算逻辑更新

💡 关键点:Vue 3 通过 Proxy 实现细粒度依赖跟踪 ,仅在数据变化时更新相关组件,避免不必要的渲染开销。也就是我们常说的:"数据变 → 视图自动变"

这一切发生得毫无感知,你甚至不用关心"如何更新",因为 Vue 全自动完成了。


🧠 小总结:Vue 的响应式系统三部曲

原理 核心作用
Proxy 劫持对象属性的读写操作
依赖追踪 记录使用了哪些响应式数据
触发更新 当数据变化时,通知所有用到它的地方更新

🧪 深入学习建议

如果你想进一步理解 Vue 响应式系统底层的实现原理,可以参考我整理的示例源码和学习记录 👇

📦 我的 GitHub 仓库(含 Vue 响应式 DEMO):

👉 github.com/chenZai90/m...


🥳 如果你觉得这篇文章还不错...

点赞 鼓励一下作者

🧠 收藏 方便以后查阅

📣 转发 给你正在学 Vue 的朋友

💬 评论区 欢迎你来交流更多疑问和见解!

相关推荐
MegatronKing2 分钟前
一个有意思的问题引起了我的反思
前端·后端·测试
鹤归时起雾.14 分钟前
CSS属性继承与元素隐藏全解析
前端·css
火星数据-Tina20 分钟前
让电竞数据实时跳动:Spring Boot 后端 + Vue 前端的完美融合实践
前端·vue.js·spring boot
fruge31 分钟前
前端可视化家庭账单:用 ECharts 实现支出统计与趋势分析
前端·javascript·echarts
IT_陈寒1 小时前
Vue3性能优化实战:5个被低估的Composition API技巧让你的应用快30%
前端·人工智能·后端
嘻嘻哈哈猿人1 小时前
从 0 到 1 实现一个支持 @ 提及用户的输入框组件(Vue3 实战)
前端·vue.js
东土也1 小时前
Vue 项目 Nginx 部署路径差异分析与部署指南
前端
云枫晖1 小时前
Vue3 响应式原理:手写实现 ref 函数
前端·vue.js
合作小小程序员小小店1 小时前
web网页开发,在线%宠物销售%系统,基于Idea,html,css,jQuery,java,ssh,mysql。
java·前端·数据库·mysql·jdk·intellij-idea·宠物
荔枝吖1 小时前
html2canvas+pdfjs 打印html
前端·javascript·html