一、单元测试编写
创建readonly.spec.ts文件,编写测试代码。readonly创建的数据可以被读取,但是不可以被set.
import { readonly} 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(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();
})
})
二、代码功能实现
export function readonly(raw){
return new Proxy(raw, {
get(target,key){
const res = Reflect.get(target,key);
return res;
},
set(target,key,value){
//此处可以抛出一个warn
console.warn('key:${key} set 失败,因为 target 是 readonly',target)
return true;
}
})
}
三、执行测试
完成后,我们可以通过yarn test --watchAll执行所有的测试。
yarn test --watchAll
四、代码重构
完成功能后,我们可以对代码进行优化重构。
baseHandlers.ts
import {track, trigger} from "./effect";
const get = createGetter();
const set = createSetter();
const readonlyGet = createGetter(true)
function createGetter(isReadonly = false){
return function get(target,key){
const res = Reflect.get(target,key);
if(!isReadonly){
track(target,key)
}
return res;
}
}
function createSetter (){
return function (target, key, value) {
const res = Reflect.set(target, key, value);
trigger(target, key);
return res;
}
}
export const mutableHandler = {
get,
set
}
export const readonlyHandlers = {
get:readonlyGet,
set(target,key,value){
console.warn('key:${key} set 失败,因为 target 是 readonly',target)
return true;
}
}
reactive.ts
import { mutableHandler, readonlyHandlers } from './baseHandlers';
export function reactive(raw){
return createActiveObject(raw,mutableHandler)
}
export function readonly(raw){
return createActiveObject(raw,readonlyHandlers);
}
function createActiveObject(raw: any, baseHandlers){
return new Proxy(raw,baseHandlers);
}