reactive
- 如果不是一个对象的话就返回了
- vue3 用的是 proxy 来做代理,不用再去重写数组的方法
- 也不用递归遍历对象进行数据劫持增加get、set方法所以性能好了很多
reactive/src/reactive.ts
import { isObject } from "@vue/shared";
import { MutableReactiveHandler } from "./baseHandlers";
function createReactiveObject(target) {
// 如果不是对象的话 就返回
if (!isObject) {
return target;
}
const proxy = new Proxy(target, MutableReactiveHandler);
return proxy;
}
export function reactive(target) {
return createReactiveObject(target);
}
reactive/src/baseHandlers.ts
export const MutableReactiveHandler = {
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);
return res;
},
set(target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver);
return result;
},
};
如果 reactive 传入的对象已经被代理了怎么办?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vue3</title>
</head>
<body>
<script type="module">
import { reactive } from "./reactivity.js";
const data = { name: "aa", age: "bb" };
const state = reactive(data);
const state1 = reactive(data);
</script>
</body>
</html>
就是准备一个 Map 去记录当前这个 target 是否被代理过
reactive/src/reactive.ts
import { isObject } from "@vue/shared";
import { MutableReactiveHandler } from "./baseHandlers";
const proxyMap = new WeakMap();
function createReactiveObject(target) {
// 如果不是对象的话 就返回
if (!isObject) {
return target;
}
// 如果属性被代理过的处理
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return target;
}
const proxy = new Proxy(target, MutableReactiveHandler);
// 代理完成之后放到map上
proxyMap.set(target, proxy);
return proxy;
}
export function reactive(target) {
return createReactiveObject(target);
}
如果传入的是代理的对象怎么办?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>vue3</title>
</head>
<body>
<script type="module">
import { reactive } from "./reactivity.js";
const data = { name: "aa", age: "bb" };
const state = reactive(data);
// 代理过之后再重新代理
const state1 = reactive(data)
// 当传入的是代理之后的对象怎么办
const state2 = reactive(state);
</script>
</body>
</html>
reactive/src/reactive.ts
export const enum ReactiveFlags {
IS_REACTIVE = "__v_isReactive",
}
function createReactiveObject(target) {
...
// 只有代理过才可能走MutableReactiveHandler中的get方法
// 普通对象相当于取值 只能是undefined 就不会走这个判断
if (target[ReactiveFlags.IS_REACTIVE]) {
return target;
}
...
}
...
reactive/src/baseHandlers.ts
export const MutableReactiveHandler = {
get(target, key, receiver) {
// 判断是否被代理过
if (key == ReactiveFlags.IS_REACTIVE) {
return true;
}
...
},
...
};