shallowReadonly
TIP
本篇笔记对应的分支号为: main分支: 4c145d8
这里引用官方文档中关于 shallowReadonly 的描述:
概念
创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。
shallow 本身有 浅层,表层 的意思。那这句话是什么意思呢?拆开来理解的话,shallowReadonly 主要包含以下两个特征:
shallowReadonly返回的是一个readonly对象;shallowReadonly返回的对象内嵌套的对象 不是readonly对象;
我们通过测试用例来加深下理解:
// src/reactivity/__tests/shallowReadonly.spec.ts
import { shallowReadonly, isReadonly } from '../reactive'
describe('shallowReadonly', () => {
test('should not make non-reactive properties reactive', () => {
const props = shallowReadonly({ n: { foo:1 }})
// 最外层的对象是 readonly 对象
expect(isReadonly(props)).toBe(true)
// 内部嵌套的对象不是 readonly 对象
expect(isReadonly(props.n)).toBe(false)
})
})
现在我们已经知道了 shallowReadonly 的功能,那我们该如何实现它呢?
还记得我们是怎么实现 readonly 的么?createGetter 是否返回 readonly 对象取决于传入的第一个参数 isReadonly 是否为 true。我们可以如法炮制,给 createGetter 传入第二个参数: isShallow 用于标记是否需要返回 shallow 对象,之后根据该值进行判断: 如果 isShallow === true, 直接返回 res , 否则保持原有逻辑。:
// src/reactivity/baseHandlers.ts
/**
* 用于生成 get 方法
* @param isReadonly 是否是 readonly 对象
* @returns
*/
function createGetter(isReadonly = false, isShallow = false) {
return function(target, key) {
// 判断是否是 reactive 对象
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly
} else if (key === ReactiveFlags.IS_READONLY) {
// 判断是否是 readonly 对象
return isReadonly
}
const res = Reflect.get(target, key)
// 如果是 shallow,直接返回结果
if (isShallow) return res
if (isObject(res)) {
return isReadonly ? readonly(res) : reactive(res)
}
// 收集依赖
!isReadonly && track(target, key)
return res
}
}
在此之后,我们需要为 shallowReadonly 定义 shallowReadonlyHandlers。由于 shallowReadonly 返回的也是 readonly 对象,它与 readonly 的唯一区别在于 createGetter 的第二个参数是否是 true。因此,我们可以复用之前定义的 readonlyHandlers。
还记得我们之前抽取的 extend 公共方法么? 这里它又派上用场啦:
// src/reactivity/baseHandlers.ts
import { isObject, extend } from '../shared'
const shallowReadonlyGet = createGetter(true, true)
export const shallowReadonlyHandlers = extend({}, readonlyHandlers, {
get: shallowReadonlyGet
})
最后,我们只需要在 reactive.ts 中定义 shallowReadonly 方法即可:
// src/reactivity/reactive.ts
import { mutableHandlers, readonlyHandlers, shallowReadonlyHandlers } from './baseHandlers'
/**
* 创建 shallowReadonly 对象
* @param raw
* @returns
*/
export const shallowReadonly = raw => {
return createActiveObject(raw, shallowReadonlyHandlers)
}
Loading...