vue3源码解析之响应式原理——基础篇

127 阅读2分钟

所谓响应式指的是当A数据变化后,作为依赖A的变量B也将随之发生变化。Vue3利用了proxy的handler中操作get和set完成了大部分数据的劫持代理。

1、什么是响应式

所谓响应简单举个例子就是指当A变化后,作为依赖A的B也将随之发生变化。A的变化会主动改变B。

2、响应式的基本使用

const count = ref(1);
const dobuleCount = count.value * 2;
count.value = 2;
console.log(count.value,dobulecount) // 2,4

const introduce = reactive({ name: "张三", age: 18 })
introduce.name = "李四"
console.log(introduce)              // { name: "李四", age: 18}

3、响应式的基本流程

  1. 判断等待代理的变量是否是对象,如果是不是直接返回等待代理的变量,如果是进行步骤二
  2. 判断等待代理的变量是否已经代理,并且是否使用reactivereadonly(定义对象非响应式)、或未使用readonly包含reactive定义了(因为结论是直接返回,但是readonly的结果不具备响应式),如果是则直接返回,如果没有进行步骤三

但如果这里非要使用readonly(reactive())定义对象的话,实际应该还是被重新代理了,但是readonlyset时会进行拦截进行“不允许修改”的提醒

  1. 判断等待代理的变量是否已经代理过,如果已代理过,则直接返回之前缓存的已代理对象,如果没有进行步骤4
  2. 代理对象,对象分类型处理,将Object、Array合并处理,Map、Set、weakMap、weakSet合并处理
  3. 返回被代理完成的对象

reactive基础.jpg

4、相较于Vue2,Vue3的响应式设计优点在哪?

  1. 相较于definePropertyproxy能够代理更多类型数据,比如可以代理Map、Set等
  2. defineProperty代理对象时,需要遍历对象对每个属性逐个代理,proxy则不需要,遍历过多就会导致性能下降,因此不建议使用太深层次的响应式数据
  3. proxy对数组的处理更方面(待定)
  4. ...待补充

5、proxy的缺点

  1. 兼容性较差,不支持老版ie,对大多数人来说其实影响不大

5、响应式的缺点

  1. 不能使用解构赋值解构响应式变量(原因:解构赋值的过程并不是从get进行的);
  2. 根据文档描述定义,ref应当用来使用基本类型数据,reactive用来定义其他类型数据,但在实际应用过程中,reactive有时候会带来一些小麻烦,比如:

批量更新reactive包裹的数据时,无法直接替换reactive定义的变量,这会导致丢失响应性。这就不太适用于刷新操作,因为刷新后需要重新赋值。但可以考虑使用ref,只是不太符合规范

3.ref定义的响应式变量访问繁琐,需要使用.value进行配合访问。