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

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

相关推荐
2503_928411563 小时前
9.26 数据可视化
前端·javascript·信息可视化·html5
我叫唧唧波3 小时前
【打包工具】webpack基础
前端·webpack
知识分享小能手5 小时前
React学习教程,从入门到精通,React 单元测试:语法知识点及使用方法详解(30)
前端·javascript·vue.js·学习·react.js·单元测试·前端框架
Ares-Wang7 小时前
Vue3 》》vite》》TS》》封装 axios ,Promise<T>
vue.js·typescript
PineappleCoder8 小时前
搞定用户登录体验:双 Token 认证(Vue+Koa2)从 0 到 1 实现无感刷新
前端·vue.js·koa
EveryPossible9 小时前
展示内容框
前端·javascript·css
伊织code9 小时前
WebGoat - 刻意设计的不安全Web应用程序
前端·安全·webgoat
子兮曰9 小时前
Vue3 生命周期与组件通信深度解析
前端·javascript·vue.js
拉不动的猪9 小时前
回顾关于筛选时的隐式返回和显示返回
前端·javascript·面试
yinuo9 小时前
不写一行JS!纯CSS如何读取HTML属性实现Tooltip
前端