一、单元测试编写 对于嵌套的对象数据结构,也需要是响应式。reactive嵌套对象测试代码如下:
test("nested reactive", () => {
const original = {
nested: {
foo: 1,
},
array: [{bar: 2}],
}
const observed = reactive(original);
expect(isReactive(observed.nested)).toBe(true);
expect(isReactive(observed.array)).toBe(true);
expect(isReactive(observed.array[0])).toBe(true);
})
而readonly嵌套对象测试则在原来测试代码上加上2行即可
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(isReadonly(wrapped.bar)).toBe(true);
//新增
expect(isReadonly(original.bar)).toBe(false);
expect(wrapped.foo).toBe(1)
})
二、代码功能实现 在原有基础上新增是否是对象的判断,是则判断是否只读,不是只读则调用reactive将其变为响应式。 src/reactivity/baseHandlers.ts
import {track, trigger} from "./effect";
import { ReactiveFlags,reactive,readonly} from "./reactive";
//新增
import {isObject} from "../shared/index"
const get = createGetter();
const set = createSetter();
const readonlyGet = createGetter(true)
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);
// 新增,看看res是不是object
if(isObject(res)){
return isReadonly? readonly(res) : reactive(res)
}
if(!isReadonly){
track(target,key)
}
return res;
}
}
function createSetter (){
return function set (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;
}
}
其中isObject判断方法如下 src/sahred/index.ts
export const extend = Object.assign;
新增
export const isObject = (val) => {
return val !== null && typeof val === "object";
}
三、执行测试
执行测试脚本,测试通过
yarn test reactive