⚙️ 《响应式原理》— 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 的朋友

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

相关推荐
林太白2 分钟前
Nuxt3 功能篇
前端·javascript·后端
YuJie3 分钟前
webSocket Manager
前端·javascript
Mapmost18 分钟前
Mapmost SDK for UE5 内核升级,三维场景渲染效果飙升!
前端
Mapmost21 分钟前
重磅升级丨Mapmost全面兼容3DTiles 1.1,3DGS量测精度跃升至亚米级!
前端·vue.js·three.js
wycode27 分钟前
Promise(一)极简版demo
前端·javascript
浮幻云月28 分钟前
一个自开自用的Ai提效VsCode插件
前端·javascript
DevSecOps选型指南29 分钟前
SBOM风险预警 | NPM前端框架 javaxscript 遭受投毒窃取浏览器cookie
前端·人工智能·前端框架·npm·软件供应链安全厂商·软件供应链安全工具
__lll_37 分钟前
Docker 从入门到实战:容器、镜像与 Compose 全攻略
前端·docker
木春1 小时前
react组件化思维:高复用性 UI 设计之道
前端·react.js