Vue3 Ref Null

Posted on  by admin

isRef()

Lazy 的 effect()

effect() 和 reactive(). markRaw() 函数用于让数据不可被代理.

shallowReactive()

调度执行 effect - scheduler

调度执行 effect - scheduler. 异步副作用和 invalidate. watchEffect() 与 effect() 的区别.

track() 与 trigger(). Lazy 的 effect(). effect 的其他选项 onTrack 和 onTrigger.

reactive() 函数接收一个对象作为参数,并返回一个代理对象。.

  • effect() 函数用于定义副作用,它的参数就是副作用函数,这个函数可能会产生副作用,例如上面代码中的 document.body.innerText = obj.text。在副作用函数内的响应式数据会与副作用函数之间建立联系,即所谓的依赖收集,当响应式数据变化之后,会导致副作用函数重新执行。.
  • 有些数据,我们要求对用户是只读的,此时可以使用 readonly() 函数,它的用法如下:.
  • 类似于浅响应,shallowReadonly() 定义浅只读数据,这意味着,深层次的对象值是可以被修改的,在 Vue 内部 props 就是使用 shallowReadonly() 函数来定义的,用法如下:.
  • 判断数据对象是否是 reactive:.
  • 用于判断数据是否是 readonly:.
  • 用于判断对象是否是代理对象(reactive 或 readonly):.
  • Object 、Array、Map、Set、WeakMap、WeakSet.

非 Object.isFrozen:. 非 VNode,Vue3 的 VNode 对象带有 __v_skip: true 标识,用于跳过代理(实际上,只要带有 __v_skip 属性并且值为 true 的对象,都不会是被代理),例如:.

markRaw() 函数用于让数据不可被代理:. 实际上 markRaw 函数所做的事情,就是在数据对象上定义 __v_skip 属性,从而跳过代理:.

effect() 和 reactive()

ReactiveFlags 是一个枚举值:. 实际上 markRaw() 函数就是使用类似的方式实现的。所以我们不必像如上代码那么做,但是在一些高级场景或许会用到这些值。. 下面简单介绍一下 ReactiveFlags 中各个值得作用:.

代理对象会通过 ReactiveFlags.raw 引用原始对象. 原始对象会通过 ReactiveFlags.reactive 或 ReactiveFlags.readonly 引用代理对象.

track() 与 trigger()

代理对象根据它是 reactive 或 readonly 的, 将 ReactiveFlags.isReactive 或 ReactiveFlags.isReadonly 属性值设置为 true。. 定义响应式对象 obj,并在 effect 内读取它的值,这样 effect 与数据之间就会建立“联系”,接着我们连续三次修改 obj.count 的值,会发现 console.log 语句共打印四次(包括首次执行)。. 想像一下,假如我们只需要把数据的最终的状态应用到副作用中,而不是每次变化都重新执行一次副作用函数,这将对性能有所提升。实际上我们可以为 effect 传递第二个参数作为选项,可以指定“调度器”。所谓调度器就是用来指定如何运行副作用函数的:.

ref()

我们指定 effect 的调度器为 queueJob,job 实际上就是副作用函数,我们将副作用函数缓冲到 queue 队列中,并在 microtask 中刷新队列,由于队列不会重复缓冲相同的 job,因此最终只会执行一次副作用函数。. 这实际上就是 watchEffect() 函数的实现思路。. watchEffect() 函数并不在 @vue/reactivity 中提供,而是在 @vue/runtime-core 中提供,与 watch() 函数一起对外暴露。.

shallowReadonly()

这与我们上面刚刚实现的自定义调度器的 effect 的效果实际上是一样的。. 异步副作用是很常见的,例如请求 API 接口:. 当 obj.foo 变化后,意味着将会再次发送请求,那么之前的请求怎么办呢?是否应该将之前的请求标记为 invalidate?. 如果不抛弃无效的副作用,那么就会产生竟态问题。实际上,我们很容易就能通过封装 effect() 函数支持注册“无效回调”的功能:. 如果我们再加上调用器,那实际上就非常接近 watchEffect 的真实实现了。.

什么时候需要 invalidate 掉一个副作用函数呢?.

isProxy()

在组件中定义的 effect,需要在组件卸载时将其 invalidate. 在数据变化导致 effect 重新执行时,需要 invalidate 掉上一次的 effect 执行.

用户手动 stop 一个 effect 时. @vue/reactivity 提供了 stop 函数用来停止一个副作用:.

effect() 函数会返回一个值,这个值其实就是 effect 本身,我们通常命名它为 runner。.

把这个 runner 传递给 stop() 函数,就可以停止掉这个 effect。后续对数据的变更不会触发副作用函数的重新执行。.