一、响应式系统
1. Proxy-based 响应式代理
Vue3的核心创新之一是摒弃了Vue2基于Object.defineProperty的响应式系统,转而采用ES6的Proxy来实现数据代理。Proxy可以直接代理整个对象,无需递归遍历其属性,提供了一种更高效、更全面的数据拦截机制。当对代理对象进行读取、设置、删除、枚举等操作时,Proxy可以透明地触发相应的处理器函数(handler)。
在Vue3中,响应式对象通过reactive()函数创建,该函数返回一个由Proxy包装的目标对象。当访问或修改这个代理对象的属性时,Proxy会执行以下操作:
get(): 当访问属性时,触发依赖收集。如果当前运行环境处于组件渲染或计算属性计算过程,对应的依赖(即“反应性依赖”)会被记录到对应的副作用跟踪器(如组件的渲染函数或computed的getter)中。
set(): 当修改属性值时,触发依赖通知。通过对比新旧值判断是否真正发生了变更,如果有变更,则遍历并通知之前收集的所有依赖,触发它们重新执行(如重新渲染组件或重新计算computed属性)。
has()、deleteProperty()、**ownKeys()**等:同样支持对数组索引、新增/删除属性等操作的响应式处理。
2. 软引用与依赖收集
Vue3采用基于依赖收集的订阅发布模式,通过Effect(副作用)的概念来管理依赖关系。当访问响应式对象的某个属性时,对应的副作用(如渲染函数)会被标记为该属性的依赖。当属性值发生变化时,会触发所有依赖的重新执行。
Vue3还引入了**软引用(Ref)**的概念,通过ref()函数创建。软引用内部封装了一个值,并提供.value属性访问该值。Vue3的响应式系统能够识别ref对象并在访问时正确地收集其依赖。ref与reactive的区别在于,ref通常用于包装基本类型和原始对象,而reactive用于创建深度响应式的对象或数组。