vue3 与 vue2 主要差异之一无疑是响应式实现上的改变。本文主要阐述响应式原理的实现方式解析以及核心源码阅读的注释理解。
本文主要对响应式实现原理进行逻辑梳理,舍弃枯燥无味的代码,只用图解/文字进行功能描述,具体实现请自行阅读。保重!!!
如果问题,虚心求教,还请指出!!!
先回顾一下Vue2的响应式原理:
灰色-初始化声明,蓝色-收集副作用,红色-触发副作用
个人整理绘制,有误还望指出
Vue2响应式原理流程:
构建响应式数据:
以data选项为入口,对data
对象使用Object.defineProperty
对每个字段设置 getter/setter
拦截器进行拦截,同时为每个字段都创建了一个dep集合
,用于收集跟字段有关的所有依赖对象(watcher)。如果字段值是 arrar/object
,进行递归处理。由于vue2无法监听数组长度、索引值的改变,只能通过扩展数组常用的api方法(push/pop…),进行 setter
拦截。
依赖收集:
依赖收集主要发生在 computed
、watch
、update(render)
过程。
如果声明 computed
选项,在初始化computed字段
时,会为每个computed字段
声明一个对应的watcher实例
依赖对象,同时在vm实例上直接挂载computed字段
,使用定义的computed函数作为字段的getter
拦截器,并且默认执行一次来获取初始值。在计算时,如果有使用响应式字段,会触发字段的getter
拦截器,这时就会发生依赖收集,将computed字段
对应的watcher实例
加入响应字段对应的 dep集合
中,同时也把 dep集合
存在 watcher实例中
(双向绑定)。computed字段默认是响应式的,所以也维护了一个对应的dep集合
,依赖收集同data对象字段
。如果为computed字段
设置指定 set
,作为computed字段的setter拦截器。
computed字段具有缓存cache属性,当依赖的响应字段更新,并会立即触发依赖更新,只打上需要重新计算的标识(dirty=true),当依赖重新读取computed字段时,在重新计算获取最新值;如果直接通过set赋值,不需要computed重新计算依赖就能获取最新值。
如果声明 watch
选项 / $watch
,在遍历每个watch时,会为每个watch都创建一个对应的watcher实例
依赖对象,以及解析监听的响应字段,获取监听字段的初始值&#x