版本vue3.3.4
1. vue3 源码地址
https://github.com/vuejs/core
2.从单测着手
先看package.json的单测依赖
"test": "vitest", 文档地址 https://cn.vitest.dev/guide/testing-types.html
Vitest API 解释
describe
:形成一个作用域test
/it
:定义了一组关于测试期望的方法,它接收测试名称和一个含有测试期望的函数expect
:创建断言toBe
:可用于断言基础对象是否相等,或者对象是否共享相同的引用toEqual
断言实际值是否等于接收到的值或具有相同的结构(如果是对象,则递归比较它们)。你可以在此示例中看到toEqual
和 toBe 之间的区别:
3.先看reactive单测
找到core\packages\reactivity\__tests__\reactive.spec.ts 和reactivity\__tests__\reactiveArray.spec.ts
isReactive:检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
就是向 reactive
传递一个对象,会返回一个新对象,两个对象类型一致,数据长得一致,但引用不同。
通过 reactive
执行后返回的响应数据,对其做任何写/删操作,都能同步地同步到原始数据。
反过来直接修改原始数据,响应数据也能获取的最新数据。
证明了通过 Proxy 实现响应式数据的巨大好处之一:可以劫持数组的所有数据变更。这比vue2有了较大的提升
在vue2中,响应式数据必须一开始就声明好key,如果一开始不存在此属性值,也必须先设置一个默认值。通过现在这套技术方案,vue3的响应式数据的属性值终于可以随时添加删除了
这两个单测说明了,对于同一个原始数据,执行多次 reactive
或者嵌套执行 reactive
,返回的结果都是同一个响应数据。说明 reactive
文件内维持了一个缓存,以原始数据为key,以其响应数据为value,若该key已存在value,则直接返回value。
4.ref单测
找到 packages\reactivity\__tests__\ref.spec.ts
传递 ref
函数一个数字,也能返回一个 Ref
对象,其value值为当时传递的数字值,且允许修改这个value。
对嵌套的 Ref
数据的取值,只需要最开始使用.value,内部的代理数据不需要重复调用.value
vi.fn 创建一个函数的模拟,尽管可以在没有一个的情况下启动。每次调用一个函数时,它都会存储它的调用参数、返回值和实例。此外,你可以使用 methods 操纵其行为。 如果没有给出函数,mock 将在调用时返回 undefined
。
toHaveBeenCalledTimes 此断言检查函数是否被调用了特定次数。需要将 spy 函数传递给 expect
。
给effect传递了一个函数,其内部做了一个赋值操作,将 ref
函数返回结果的value(a.value)赋值给dummy。然后这个函数会默认先执行一次,使得dummy变为1。而当a.value变化时,这个effect函数会重新执行,使得dummy变成最新的value值。
也就是说,如果向effect传递一个方法,会立即执行一次,每当其内部依赖的ref数据发生变更时,会重新执行