在我们使用reactive & readonly时会发现,如果传入的是深层嵌套数据结构也能够进行响应式包裹或只读约束,之前实现的呢只是浅层的,今天来完善一下这两个深层嵌套的问题,代码也非常简单,实现方式如出一辙
reactive
readonly
结语
reactive
测试
首先就是看看深层是不是响应式
it('nested reavtive', () => {
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)
})
实现
实现我们只需要在代理get的时候进行判断,看看是否需要再进行reactive(XXX)调用
这里判断是不是对象以后用的会非常多所以抽离出去到 shared 就行
function createGetter(isReadonly = false) {
return function get(target, key) {
const res = Reflect.get(target, key)
// 判断是不是 reactive
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly
}
// 判断是不是 对象
// shared: export const isObject = (value) => value !== null && typeof value === 'object'
if (isObject(res)) {
return reactive(res)
}
// 依赖收集
// 抽离公共,判断是否需要收集依赖<readonly>
!isReadonly && track(target, key)
return res
}
}
readonly
测试
首先就是看看深层是不是约束为只读属性了
it('should make nested values readonly', () => {
// readonly 不可以被set<改写>
const original = { foo: 1, bar: { baz: 2 } }
const wrapped = readonly(original)
expect(wrapped).not.toBe(original)
expect(isReadonly(wrapped)).toBe(true)
expect(isReadonly(original)).toBe(false)
expect(isReadonly(wrapped.bar)).toBe(true)
expect(isReadonly(original.bar)).toBe(false)
expect(wrapped.foo).toBe(1)
})
实现
实现和reactive一样,在代理get的时候进行判断,看看是否需要再进行readonly(XXX)调用
这里和reactive判断机制一样的所以用三元判断进行调用会更好,之前用的 isReadonly 现在也派上用场了
function createGetter(isReadonly = false) {
return function get(target, key) {
const res = Reflect.get(target, key)
// 判断是不是 reactive
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly
}
// 判断是不是 对象
// shared: export const isObject = (value) => value !== null && typeof value === 'object'
if (isObject(res)) {
return isReadonly
? readonly(res)
: reactive(res)
}
// 依赖收集
// 抽离公共,判断是否需要收集依赖<readonly>
!isReadonly && track(target, key)
return res
}
}
结语
源码其实都是一步一步的看,一点一点的写,不断地完善,不断重构出来的。技术是积累出来的,经验都是实践得来,希望我往后的文章能够给大家带来更多的收益,即使收效甚微,感谢!