loading

ref和reactive

# 区别

  • reactive API 对传入的 target 类型有限制,必须是对象或者数组类型,而对于一些基础类型(比如 String、Number、Boolean)是不支持的。

  • 但是有时候从需求上来说,可能我只希望把一个字符串变成响应式,却不得不封装成一个对象,这样使用上多少有一些不方便

  • 我们需要一个基本类型作为响应式,如果用reactive的话就需要reactive({value:xxx})这样传进去

  • 所以vue3就提供了ref这种写法,让你不需要手动包装成对象。所以这也是为什么ref包装的响应式对象需要.value才能拿到值的原因。

  • ref本质上还是reactive

# Vue3的响应式原理

  • Vue.js 3.0 在响应式的实现思路和 Vue.js 2.x 差别并不大,主要就是 劫持数据的方式改成用 Proxy 实现 , 以及收集的依赖由 watcher 实例变成了组件副作用渲染函数 。
  • 由于 Proxy 劫持的是整个对象,所以我们可以检测到任何对对象的修改,弥补了 Object.defineProperty API 的不足。
  • Object.defineProperty 是在初始化阶段,即定义劫持对象的时候就已经递归执行了,而 Proxy 是在对象属性被访问的时候才递归执行下一步 reactive,这其实是一种延时定义子对象响应式的实现,在性能上会有较大的提升
  • 依赖收集:劫持 get 函数,通过 Reflect.get 求值,然后会执行 track 函数收集依赖副作用函数,把当前激活的副作用函数 activeEffect 作为依赖,然后收集到 target 相关的 depsMap 对应 key 下的依赖集合 dep
  • 通知依赖更新:劫持 set 函数,主要就做两件事情, 首先通过 Reflect.set 求值 , 然后通过 trigger 函数派发通知 ,并依据 key 是否存在于 target 上来确定通知类型,即新增还是修改;trigger 函数主要做了四件事情:
  • 通过 targetMap 拿到 target 对应的依赖集合 depsMap;
  • 创建运行的 effects 集合;
  • 根据 key 从 depsMap 中找到对应的 effects 添加到 effects 集合;
  • 遍历 effects 执行相关的副作用函数。

所以每次 trigger 函数就是根据 target 和 key ,从 targetMap 中找到相关的所有副作用函数遍历执行一遍。

最近更新时间: 2022/09/28 16:26:36
最近更新
01
2023/07/03 00:00:00
02
2023/04/22 00:00:00
03
2023/02/16 00:00:00