一、编写单元测试
isReactive单元测试编写
import {reactive,isReactive} from '../reactive'
describe('reactive', () => {
it('happy path', ()=> {
const original = {foo: 1};
const observed = reactive(original);
expect(observed).not.toBe(original);
expect(observed.foo).toBe(1);
expect(isReactive(observed)).toBe(true);
expect(isReactive(original)).toBe(false)
})
})
isReadonly单元测试编写
import { readonly,isReadonly} from '../reactive'
describe("readonly", () => {
it("happy path", () => {
// not set
const original = {foo: 1,bar: {baz: 2}};
const wrapped = readonly(original);
expect(wrapped).not.toBe(original);
expect(isReadonly(wrapped)).toBe(true);
expect(wrapped.foo).toBe(1)
})
it('warn then call set', () => {
const user = readonly({
age: 10
})
console.warn = jest.fn();
user.age = 11;
expect(console.warn).toBeCalled();
})
})
二、功能实现
由于响应式对象会通过reactive进行get和set的代理,在get方法内部预先约定好获取约定键值,对于响应式对象会增加该键值,所以可以通过该键值判断该值是否是响应式对象或只读对象。
reactive.ts
export const enum ReactiveFlags {
IS_REACTIVE = "_v_isReactive",
IS_READONLY = "_v_isReadonly"
}
export function isReactive (value) {
return !!value[ReactiveFlags.IS_REACTIVE];
}
export function isReadonly (value) {
return !!value[ReactiveFlags.IS_READONLY]
}
baseHandlers.ts
function createGetter(isReadonly = false){
return function get(target,key){
if(key === ReactiveFlags.IS_REACTIVE){
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY){
return isReadonly;
}
const res = Reflect.get(target,key);
if(!isReadonly){
track(target,key)
}
return res;
}
}
三、单元测试
完成后,我们可以通过yarn test --watchAll执行所有的测试。
yarn test --watchAll