实现reactive和readonly嵌套对象转换的功能
reactive嵌套
主要实现是reactive包装过的对象里面的其他对象也是reactive的
测试用例:
import { isReactive, reactive } from "../reactive"
describe('reactive',()=>{
it('happy path',()=>{
const original = {
foo:1,
sport:{
name:'basketball',
deep:'top',
lavish:'no'
},
arr:['basketball','lake']
}
const observed = reactive(original)
expect(observed).not.toBe(original)
expect(observed.foo).toBe(1)
expect(isReactive(observed)).toBe(true)
expect(isReactive(original)).toBe(false)
expect(isReactive(observed.sport)).toBe(true)
expect(isReactive(observed.arr)).toBe(true)
})
})
主要变化如图:
其实分析一下问题,要让reactive中的对象也是reactive那主要就是在触发get的时候对获取到的res是不是对象进行不同操作,如果为对象就要让他传入reactive中响应式化。
那找到方法之后,我们就到baseHandler.ts中去做操作就可以了,如图
那由于判断一个变量是不是对象,这个函数使用很频繁,所以我们就把它抽离到shared中去,如图
然后运行测试用例,就通过了
readonly嵌套
主要实现是readonly包装过的对象里面的其他对象也是readonly的,有了reactive的基础,其实实现起来就很简单了
测试用例:
import { isReadonly, readonly } from "../reactive"
describe('readonly',()=>{
it('happy path',()=>{
// not set readonly是和reactived很类似但是不可以修改 所以就不需要依赖的收集和触发
const original = {foo:1,bar:{baz:2}}
const wrapped = readonly(original)
expect(wrapped).not.toBe(original)
expect(wrapped.foo).toBe(1)
expect(isReadonly(wrapped)).toBe(true)
expect(!isReadonly(wrapped)).toBe(false)
expect(isReadonly(wrapped.bar)).toBe(true)
expect(!isReadonly(wrapped.bar)).toBe(false)
})
it('warn then call set',()=>{
console.warn = jest.fn()
const user = readonly({
age:10
})
user.age = 11
expect(console.warn).toBeCalled()
})
})
修改如图:
直接在get中的对象判断中判断,isReadonly的话就调用readonly函数否则调用reactive函数,如图
就修改了一句代码就可以了,这就是封装优化的好处,增加功能就很简单