Vue的响应式系统是其核心魔力所在,它使得数据与视图能够自动保持同步。简单来说,当你修改数据时,视图会自动更新。这套系统在Vue 2和Vue 3中的实现方式有显著不同,但目标一致:追踪数据变化并通知依赖进行更新。
![图片[1]-什么是Vue的响应式原理?-速码派](http://www.sumapai.com/wp-content/uploads/2026/01/68a6234a7cf24952b97cf5c848fbeeba_tplv-tb4s082cfz-aigc_resize_1080_1080-1024x683.webp)
Vue 2:基于Object.defineProperty的侦测
Vue 2通过Object.defineProperty递归地遍历数据对象的所有属性,将它们转换为getter和setter。当你访问数据(getter)时,Vue会将当前的依赖(例如渲染函数或计算属性)收集起来。当你修改数据(setter)时,Vue会通知所有收集到的依赖进行更新。
// 简化的概念演示
function defineReactive(obj, key, val) {
const dep = new Dep(); // 管理依赖的集合
Object.defineProperty(obj, key, {
get() {
dep.depend(); // 收集当前依赖
return val;
},
set(newVal) {
if (newVal === val) return;
val = newVal;
dep.notify(); // 通知所有依赖更新
}
});
}
这种方式存在一些局限性:无法检测到对象属性的添加或删除(需要使用Vue.set/Vue.delete),也无法原生响应数组索引和长度的直接修改。
Vue 3:基于Proxy的代理
Vue 3使用了ES6的Proxy来重写响应式系统。Proxy可以创建一个对象的代理,从而拦截并重新定义该对象的基本操作(如属性读取、赋值、删除等)。
// 简化的概念演示
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
track(target, key); // 追踪依赖
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
trigger(target, key); // 触发更新
return result;
}
// 还可以拦截 deleteProperty、has 等操作
});
}
Proxy是“劫持”整个对象,而非单个属性,因此能完美检测属性的增删、数组索引的变化以及Map、Set等集合类型。性能也更优,因为它只在真正访问属性时才会递归转换为响应式,而非初始化时递归所有属性。
依赖收集与派发更新
无论哪种实现,核心流程都是三步:触发getter时进行依赖收集 -> 数据变化时触发setter -> 通知所有收集的依赖(如组件渲染函数watcher)进行更新。组件渲染函数执行时,会访问用到的数据,从而将自己订阅为这些数据的依赖。当数据变化时,渲染函数被重新调用,生成新的虚拟DOM,进而更新真实DOM。
因此,Vue的响应式原理本质上是一种发布-订阅模式的巧妙应用。理解它有助于你明白为什么有些操作无法触发视图更新,以及如何使用ref、reactive等API。这也是Vue高效自动更新的基石。


























暂无评论内容