Vue数据响应式原理步骤解析
作者:teeeeeeemo
Vue 的数据响应式原理是其核心特性之一,它实现了数据变化自动驱动视图更新。Vue 2.x 和 Vue 3.x 的实现方式不同,下面分别详解:
Vue 2.x 的响应式原理(基于 Object.defineProperty)
核心步骤:
数据劫持(Observer):
-遍历 data 中的每个属性,用 Object.defineProperty 重写其 getter/setter。
-每个属性关联一个 Dep 实例(依赖收集器)。依赖收集(Dependency Collection):
-当组件渲染时,会访问数据属性,触发 getter。
-此时 Dep 会记录当前 Watcher(每个组件对应一个渲染 Watcher)。派发更新(Dispatching Updates):
-当数据被修改时,触发 setter。
-Dep 通知所有关联的 Watcher 执行更新(如重新渲染组件)。数组的特殊处理:
-重写数组的 7 个方法(push/pop/shift/unshift/splice/sort/reverse),在调用这些方法时手动触发更新。
-通过 proto 继承改写后的数组方法(或直接覆盖原型)。
代码简化示例:
class Dep { constructor() { this.subs = new Set(); } depend() { if (currentWatcher) this.subs.add(currentWatcher); } notify() { this.subs.forEach(watcher => watcher.update()); } } function defineReactive(obj, key) { const dep = new Dep(); let value = obj[key]; Object.defineProperty(obj, key, { get() { dep.depend(); // 收集依赖 return value; }, set(newVal) { value = newVal; dep.notify(); // 触发更新 } }); }
局限性:
- 无法检测新增/删除属性 → 需用 Vue.set/Vue.delete。
- 数组索引/长度修改无法监听 → 需用重写的方法或 Vue.set。
- 递归遍历对象性能损耗。
Vue 3.x 的响应式原理(基于 Proxy)
Vue 3 使用 Proxy 替代 Object.defineProperty,彻底解决 Vue 2 的痛点。
核心步骤:
代理对象(Reactive):
-通过 Proxy 包裹目标对象,拦截 所有操作(增/删/改/查/遍历等)。
-每个对象关联一个 ReactiveEffect 集合。
依赖收集:
-当访问数据时,触发 get 拦截,收集当前活跃的 Effect(副作用函数)。
触发更新:
-当修改数据时,触发 set 或 deleteProperty 拦截,通知所有关联的 Effect 重新执行。
代码简化示例:
const targetMap = new WeakMap(); // 存储所有依赖 function track(target, key) { if (!activeEffect) return; let depsMap = targetMap.get(target); if (!depsMap) targetMap.set(target, (depsMap = new Map())); let dep = depsMap.get(key); if (!dep) depsMap.set(key, (dep = new Set())); dep.add(activeEffect); // 收集当前 Effect } function trigger(target, key) { const depsMap = targetMap.get(target); if (!depsMap) return; depsMap.get(key)?.forEach(effect => effect.run()); // 执行所有 Effect } const proxy = new Proxy(data, { get(target, key) { track(target, key); // 访问时收集依赖 return Reflect.get(target, key); }, set(target, key, value) { Reflect.set(target, key, value); trigger(target, key); // 修改时触发更新 return true; } });
优势:
- 支持监听动态新增/删除属性。
- 支持监听数组索引和长度变化。
- 惰性收集:仅代理访问到的属性,减少初始化开销。
- 统一处理对象/数组,无需特殊逻辑。
关键概念补充
副作用函数(Effect):
-Vue 3 使用 ReactiveEffect 封装更新逻辑(相当于 Vue 2 的 Watcher)。
-组件渲染、计算属性、侦听器都是副作用函数。
响应式 API:
-reactive():创建深层次响应式对象(基于 Proxy)。
-ref():将基本类型包装为 { value: … } 的响应式引用(通过 .value 访问)。
-computed/watch:基于 Effect 系统实现。
依赖清理:
-每次执行 Effect 前清理旧依赖,避免无效更新(如条件分支变化时)。
总结对比
特性 | Vue 2(Object.defineProperty) | Vue 3(Proxy) |
---|---|---|
对象监听 | 递归遍历属性 | 直接代理整个对象 |
新增/删除属性 | 不支持(需 Vue.set) | 支持 |
数组监听 | 需重写方法 | 直接支持索引修改 |
性能 | 初始化递归消耗大 | 按需代理,内存更优 |
兼容性 | 支持 IE9+ | 不支持 IE(需 Polyfill) |
Vue 3 的响应式系统独立为库 @vue/reactivity,可脱离框架使用。
到此这篇关于Vue数据响应式原理解析的文章就介绍到这了,更多相关Vue数据响应式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
- Vue 中ref()和 reactive()响应式数据的使用方法
- Vue3.0使用ref和reactive来创建响应式数据
- Vue3 响应式数据 reactive使用方法
- 详解vue2和vue3如何定义响应式数据
- 一文详解Vue响应式数据的原理
- Vue3关于响应式数据类型详解(ref、reactive、toRef、及toRefs)
- Vue.js响应式数据的简单实现方法(一看就会)
- vue3.x源码剖析之数据响应式的深入讲解
- 稍微学一下Vue的数据响应式(Vue2及Vue3区别)
- 使用Vue.set()方法实现响应式修改数组数据步骤
- Vue.js中provide/inject实现响应式数据更新的方法示例
- Vue3.0数据响应式原理详解