最近读了霍春阳《Vue.js设计与实现》,为了方便以后回顾,根据自己的理解简单整理了一下。
- 响应系统
- 渲染器
- 组件化
- 编译器
以上是Vue里面几个核心模块,本篇主要针对响应系统进行了整理
响应系统 响应系统是Vue最重要的一个模块,核心主要两个概念
- 响应式数据
- 副作用函数
副作用函数是指会产生副作用的函数,就是该函数的执行的结果会对其他函数的执行结果产生影响。
响应数据的实现在v3里面依赖于代理对象proxy
响应式系统的工作流程是,在读取数据时,收集该数据对应的副作用函数,在设置时执行收集的副作用函数
响应式系统整体流程的实现解决了以下问题。
- 对象没有引用时,确保垃圾回收机制的执行。
- 函数内部存在三元表达式时,避免出现不必要的更新。
- 当副作用函数发生嵌套时,内存副作用函数的执行会对activeEffect产生覆盖。
- 当数据出现自增的情况时,触发副作用函数递归调用
- 调度器的实现
- computed计算属性的实现
- watch的实现
对于响应的实现部分,又分为非原始值的响应和原始值的响应 非原始值响应包含
-
Object
对属性的读取操作通过proxy,对for...in操作则需要对ownKeys进行拦截
更合理的触发响应,比如对value相同的赋值屏蔽触发等
配置深/浅响应,深/浅只读
-
数组
数组是一个虽然异质对象,但是除了[[DefineOwnProperty]]与常规对象不同,其他都一样,所以代理对象的大部分方法都能用,比如通过索引设置或者读取值时,就能被对象的get/set拦截。但是数组通过索引修改值的操作可能会触发长度的变化,所以当通过索引修改数组时,不仅需要触发get属性的副作用函数,还需要触发length属性的副作用函数。
-
Set和Map
Set和Map有自己的属性和方法,与普通对象不同。需要对方法进行覆写,在覆写方法里面处理副作用的响应
原始值响应包含
- Boolean
- Number
- BigInt
- String
- Symbol
- undefined
- null
proxy无法对原始值进行响应,需要使用对象进行包裹,间接实现原始值的响应