Readonly 与响应式类型推导
readonly 本质上是一个只读的代理对象:它拦截 get 操作,但不进行依赖收集,并在尝试 set 时抛出警告或直接拦截。
实现结构
function createGetter(isReadonly = false, shallow = false) {
return function get(target: object, key: string | symbol, receiver: object) {
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly;
}
const res = Reflect.get(target, key, receiver);
if (shallow) {
return res;
}
if (isObject(res)) {
return isReadonly ? readonly(res) : reactive(res);
}
if (!isReadonly) {
track(target, key);
}
return res;
};
}
function createSetter() {
return function set(target: object, key: string | symbol, value: unknown, receiver: object) {
const res = Reflect.set(target, key, value, receiver);
trigger(target, key);
return res;
};
}
export const mutableHandlers = {
get: createGetter(),
set: createSetter(),
};
export const readonlyHandlers = {
get: createGetter(true),
set(target: object, key: string | symbol) {
console.warn(`key :"${String(key)}" set 失败,因为 target 是 readonly`);
return true;
},
};
export function readonly(target: object) {
return new Proxy(target, readonlyHandlers);
}
export function isReactive(value: unknown): boolean {
return !!(value && (value as any)[ReactiveFlags.IS_REACTIVE]);
}
export function isReadonly(value: unknown): boolean {
return !!(value && (value as any)[ReactiveFlags.IS_READONLY]);
}
export function isProxy(value: unknown): boolean {
return isReactive(value) || isReadonly(value);
}