本文是 Vue3 源码实战专栏的第 5 篇。
isReactive
isReactive()检查一个对象是否是由 reactive() 或 shallowReactive() 创建的代理。
使用
<script setup>
import { isReactive, reactive } from "vue";
const user1 = reactive({ name: "wendZzoo" });
const user2 = { name: "wendZzoo" };
</script>
<template>
{{ isReactive(user1) }}
{{ isReactive(user2) }}
</template>
页面上展示true false
单测
在原本的reactive单元测试上添加isReactive测试断言。
import { isReacive, reactive } from "../reactive";
describe("reactive", () => {
it("happy path", () => {
let original = { foo: 1 };
let data = reactive(original);
expect(data).not.toBe(original);
expect(data.foo).toBe(1);
// isReactive
expect(isReacive(data)).toBe(true);
expect(isReacive(original)).toBe(false);
});
});
实现
判断一个对象是否是reactive创建的代理,那在访问该对象时会触发其get操作,可以定义当前的对象上是否存在一个key来判断。
在reactive.ts文件中导出isReactive方法,
export function isReacive(value) {
return !!value['is_reactive'];
}
改造get函数,
function createGetter(isReadonly = false) {
return function get(target, key) {
let res = Reflect.get(target, key);
if (key === "is_reactive") {
return !isReadonly;
}
if (!isReadonly) {
track(target, key);
}
return res;
};
}
执行单测yarn test reactive验证isReactive方法是否正确。
优化
定义一个枚举类型来管理is_reactive这样的变量。
export const enum ReactiveFlags {
IS_REACTIVE = "__v_isReactive"
}
export function isReacive(value) {
return !!value[ReactiveFlags.IS_REACTIVE];
}
get函数中相应的修改,
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
}
isReadonly
有了isReactive的实现,isReadonly很类似。
isReadonly()检查传入的值是否为只读对象。只读对象的属性可以更改,但他们不能通过传入的对象直接赋值。
单测
在readonly.spec.ts的happy path测试用例中添加isReadonly的断言。
import { isReadonly, readonly } from "../reactive";
it("happy path", () => {
const original = { foo: 1, bar: { bar: 2 } };
const wapper = readonly(original);
expect(wapper).not.toBe(original);
expect(wapper.foo).toBe(1);
// isReadonly
expect(isReadonly(wapper)).toBe(true);
expect(isReadonly(original)).toBe(false);
});
实现
reactive.ts中导出isReadonly方法
export const enum ReactiveFlags {
IS_REACTIVE = "__v_isReactive",
IS_READONLY = "__v_isReadonly",
}
export function isReadonly(value) {
return !!value[ReactiveFlags.IS_READONLY];
}
在get函数中新增对readonly的判断
if (key === ReactiveFlags.IS_REACTIVE) {
return !isReadonly;
} else if (key === ReactiveFlags.IS_READONLY) {
return isReadonly;
}
执行所有单测yarn test验证。
Vue3源码解析:isReactive与isReadonly功能及其测试,
本文详细介绍了Vue3中的isReactive和isReadonly函数,它们用于检测对象是否由reactive或shallowReactive创建,以及在单元测试中的应用。着重讲解了这两个方法的实现和在get函数中的应用,以及如何通过ReactiveFlags进行优化。
1666





