Jest测试框架。
yarn add jest
思路
在执行reactive函数时绑定Proxy, getter时收集依赖,setter时触发依赖
reactive测试用例
describe("reactive", ()=>{
it("run reactive", ()=>{
const original = {
age: 10
}
const observed = reactive({
age: 10
})
expect(original).toBe(observed)
expect(observed).toBe(10)
})
})
测试1:两个对象是否相同
测试2:react是否能拿到值
reactive实现
import { track, trigger } from "./effect"
function reactive(raw: any){
return new Proxy(raw, {
get(target, key){
// 收集依赖
track()
return Reflect.get(target, key)
},
set(target, key, value){
const result = Reflect.set(target. key, value)
// 触发依赖
trigger()
return result
}
})
}
effect测试用例
import { reactive } from "../reactive";
import { effect } from "../effect";
describe('effect', () => {
it("run effect", () => {
const user = reactive({ age: 10 })
let age
effect(() => {
age = user.age + 1
})
expect(age).toBe(11)
// update
user.age++
expect(age).toBe(12)
})
})
思路
创建reactive当getter的时候收集依赖, setter触发依赖。
首先第一要把effect传入的回调函数保存起来。
触发依赖时把存储的`回调函数`调用一下
effect实现
/**
*
* @abstract ReactiveEffect
*/
class ReactiveEffect {
private _fn: Function
constructor(fn: Function) {
this._fn = fn
}
_run() {
activeEffect = this
this._fn()
}
}
// 全局容器
/**
* targetMap
* 存储
* [] 其中为描述词
* {
* [target]: {
* [key]: new Set([
* [effect]
* ])
* }
* }
* target 修改的对象
* key: 对象的key
* effect: 对象(用于获取_run()并调用)
*/
const targetMap = new Map()
// 收集依赖
export function track(target: any, key: any): any {
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap = new Map()
targetMap.set(target, depsMap)
}
let deps = depsMap.get(key)
if (!deps) {
deps = new Set()
depsMap.set(key, deps)
}
trackEffects(deps)
}
function trackEffects(deps: any): any {
!deps.has(activeEffect) && deps.add(activeEffect)
}
/**
* @description
* 触发依赖
*/
export function trigger(target: any, key: any): any {
const depMap = targetMap.get(target)
const deps = depMap.get(key)
for (const effect of deps) {
effect._run()
}
}
// 存储每次调用_run()时的ReactiveEffect类型对象
let activeEffect: any
export function effect(fn: Function): any {
const _effect = new ReactiveEffect(fn)
_effect._run()
}