Vue 响应式原理
2023-12-09
Vue

响应式就是能够自动跟踪数据变化,进而更新页面。要跟踪数据,在 js 里,可以拦截对象的读写,有两种方式:getter/setter 和 proxy,vue2采用前者,vue3 用的 proxy。

其过程是:

  • 代理数据
  • 依赖收集
  • 触发更新

其中,代理数据,vue2 用到 Object.defineProperty,vue3 用到 Proxy。

代理数据

Object.defineProperty

设置对象的 gettersetter 来监听对象的操作。getter 里收集依赖,setter 就是观察者,数据发生更新时,通知订阅者更新视图。

受限于 definePropertygetter/setter 无法追踪属性的新增和删除。对数组的话,监听下标会造成性能浪费,因而vue2中重写了数组方法,重写之后,有些数组属性拦截不掉,比如直接修改长度,或以下标来赋值。

Proxy

Proxy 针对整个对象,因此,无需遍历所有属性,只需代理一层,即可监听同级所有属性的变化。对于深层对象,还是要递归

依赖收集

两个类,订阅者 Dep,观察者 Watcher,Dep 收集依赖项,也就是一系列 Watcher,以便知道数据更新了该更新哪里的视图

Watcher 需要知道自己属于哪里,是 data、computed、watch。


拿 Vue2 来说。Vue初始化后,data 会转换成 getter/setter 形式,来追踪数据。当渲染函数执行的时候,会触发一次getter,此时收集依赖项,也就是一个个 Watcher。之后更改数据,会触发 setter,通知收集到的相关 Watcher 更新页面