Vue 渲染时的数据绑定本质是通过对象属性劫持(Vue 2用Object.defineProperty、Vue 3用Proxy)、依赖关系图谱(Dep收集Watcher)和响应式更新链路(getter收集、setter通知)实现数据到视图的自动传导。

Vue 渲染时的数据绑定,本质是靠一套精细的内存模型支撑的——它不是简单地“监听变量”,而是通过对象属性劫持 + 依赖关系图谱 + 响应式更新链路,实现数据变化到视图刷新的自动传导。
响应式数据的内存结构:Observer 与 reactive 对象
在 Vue 2 中,每个响应式 data 属性都被 Object.defineProperty 包裹,拥有独立的 getter/setter;Vue 3 则用 Proxy 代理整个对象。无论哪种方式,核心目标一致:让读取(get)能收集依赖,写入(set)能触发通知。
- 每个响应式对象内部都关联一个 Dep 实例(依赖收集器),用于存储所有依赖它的 Watcher
- 每个计算属性或模板表达式在首次求值时,会进入“依赖收集态”:访问某个响应式字段 → 触发其 getter → 把当前 Watcher 记录进该字段的 Dep
- 这个过程形成一张“谁依赖谁”的内存关系网,不是全局扫描,而是按需建立、按需更新
模板编译与依赖映射:Compile 如何定位响应式字段
Vue 的模板不是直接执行 JS,而是先编译成渲染函数(render function)。这个过程会静态分析插值、指令和表达式,提取出所有被访问的响应式路径(如 user.name、list[0].id)。
Miller (mlr) 是一个命令行工具,用于查询、整形和重新格式化名称索引数据,如 CSV、TSV、JSON 和 JSON Lines。它将 awk、sed、cut、join 和 sort 的功能整合到一个专为结构化数据处理而构建的单一工具中。
- v-model、v-bind、{{ }} 等语法最终都会转化为对响应式属性的访问调用
- 编译阶段生成的 render 函数中,每处属性读取都会触发对应 getter,从而完成依赖注册
- 如果访问的是非响应式值(比如字面量、局部变量),就不会进入 Dep,也不会被追踪
Watcher 作为更新中枢:如何触发视图重绘
Watcher 是连接数据与视图的关键桥梁。每个组件实例、每个计算属性、每个侦听器,背后都有至少一个 Watcher 实例。
立即学习“前端免费学习笔记(深入)”;
- Watcher 初始化时会执行一次 getter,触发依赖收集,把自己加入所有被读取字段的 Dep
- 当某个响应式字段 set 被调用,它对应的 Dep 就会遍历所有 Watcher 并调用其
update() - 组件 Watcher 的 update 默认是异步的(走 nextTick 队列),批量合并 DOM 更新,避免重复渲染
为什么有些修改不触发更新?常见内存陷阱
响应式系统只对“已存在且被定义为响应式”的属性生效。以下情况不会被追踪:
- 直接给响应式对象添加新属性(Vue 2 需
Vue.set,Vue 3 可直接赋值但需确保 Proxy 已覆盖该对象) - 对数组使用下标直接赋值(如
arr[1] = 'new'),Vue 2 不响应,Vue 3 支持 - 用
Object.freeze()或const声明的对象,Proxy/defineProperty 无法劫持 - 解构后的变量(如
const { name } = user)脱离响应式上下文,修改它不影响原对象

















