Vue 2的响应式原理:
- 初始化阶段:在创建Vue实例时,遍历data对象的属性,使用Object.defineProperty方法为每个属性定义getter和setter。
- Getter拦截:在getter中,收集当前属性的依赖关系。Vue通过一个Dep(Dependency)对象来管理依赖。
- Setter拦截:在setter中,当属性值发生变化时,触发依赖的更新。Vue通过Dep对象通知所有依赖进行更新。
- 依赖收集:每个组件实例都有一个Watcher(观察者)对象,负责管理组件的更新和依赖。在模板编译过程中,将模板中的数据访问转化为对应的Getter调用,并在Getter中进行依赖收集。
示意图:
+---------------------+
| Vue实例 |
+---------------------+
| data |
| computed |
| methods |
| watch |
+---------------------+
| ↑
| |
v |
+---------------------+
| 数据劫持 Proxy/ |
| Object.defineProperty |
+---------------------+
| ↑
| |
v |
+---------------------+
| 依赖收集 |
+---------------------+
| ↑
| |
v |
+---------------------+
| Watcher |
+---------------------+
| ↑
| |
v |
+---------------------+
| 视图更新 |
+---------------------+
在上面的示意图中,Vue实例包含了data、computed、methods、watch等选项。数据劫持阶段通过Proxy对象或Object.defineProperty方法来实现对data中属性的劫持。在依赖收集阶段,Watcher对象负责依赖的管理和更新。当数据发生变化时,Watcher会通知对应的视图进行更新。
Vue 3的响应式原理:
- 初始化阶段:创建一个Proxy对象,代理目标对象(例如data对象)。
- Getter拦截:在Proxy的get拦截器中,收集属性的依赖关系。Vue使用一个ReactiveEffect对象来管理依赖。
- Setter拦截:在Proxy的set拦截器中,当属性值发生变化时,触发依赖的更新。Vue通过ReactiveEffect对象通知所有依赖进行更新。
- 依赖收集:Vue 3使用一个特殊的函数createReactiveEffect来包装组件中的代码块,并在执行过程中收集依赖。通过追踪执行过程中访问的响应式属性,实现依赖的自动收集
vue 3使用了基于Proxy的响应式系统,下面是一个简化的示意图来描述Vue 3的响应式原理:
+-----------------------------------+
| Vue 实例 |
+-----------------------------------+
| data |
| computed |
| methods |
| watch |
+-----------------------------------+
| ↑
| |
v |
+-----------------------------------+
| 响应式 Proxy |
+-----------------------------------+
| ↑
| |
v |
+-----------------------------------+
| 响应式依赖追踪 |
+-----------------------------------+
| ↑
| |
v |
+-----------------------------------+
| 更新触发 |
+-----------------------------------+
| ↑
| |
v |
+-----------------------------------+
| 视图更新 |
+-----------------------------------+
在这个示意图中,Vue实例包含了data、computed、methods和watch等选项。在Vue 3中,使用Proxy对象实现对data中属性的响应式劫持。当访问或修改属性时,Proxy对象会捕获到对应的操作,并触发依赖追踪。
依赖追踪阶段会收集属性的依赖关系,确保属性与相关的响应式依赖建立关联。当依赖的数据发生变化时,触发更新操作,更新会被通知到相关的视图进行更新。
补充说明:
- Vue 3的响应式系统支持对数组的响应式跟踪,可以监听到数组元素的变化。
- Vue 3的响应式系统支持动态新增和删除属性,而Vue 2需要事先定义好所有的响应式属性。
- Vue 3的响应式系统性能更好,使用Proxy比Object.defineProperty更高效,并且能够处理大型对象的访问和修改操作。