您好,登录后才能下订单哦!
Vue3 的响应式系统是其核心特性之一,而 reactive
是 Vue3 中用于创建响应式对象的核心 API。本文将深入分析 reactive
的源码实现,帮助读者更好地理解 Vue3 的响应式机制。
在 Vue3 中,reactive
函数用于将一个普通对象转换为响应式对象。响应式对象的属性在被访问或修改时,会自动触发依赖收集和更新。
import { reactive } from 'vue';
const state = reactive({
count: 0,
});
state.count++; // 触发更新
reactive
的源码位于 packages/reactivity/src/reactive.ts
文件中。其主要逻辑如下:
export function reactive<T extends object>(target: T): UnwrapNestedRefs<T> {
// 如果 target 已经是响应式对象,直接返回
if (target && (target as any).__v_isReactive) {
return target;
}
// 创建响应式对象
return createReactiveObject(
target,
false,
mutableHandlers,
mutableCollectionHandlers,
reactiveMap
);
}
createReactiveObject
是 reactive
的核心实现函数,负责创建响应式对象。其源码如下:
function createReactiveObject(
target: Target,
isReadonly: boolean,
baseHandlers: ProxyHandler<any>,
collectionHandlers: ProxyHandler<any>,
proxyMap: WeakMap<Target, any>
) {
// 如果 target 不是对象,直接返回
if (!isObject(target)) {
return target;
}
// 如果 target 已经是 Proxy 对象,直接返回
if (target.__v_raw && !(isReadonly && target.__v_isReactive)) {
return target;
}
// 如果 target 已经有对应的 Proxy 对象,直接返回
const existingProxy = proxyMap.get(target);
if (existingProxy) {
return existingProxy;
}
// 根据 target 的类型选择合适的 handler
const handler = isCollectionType(target) ? collectionHandlers : baseHandlers;
// 创建 Proxy 对象
const proxy = new Proxy(target, handler);
// 将 Proxy 对象存入 proxyMap
proxyMap.set(target, proxy);
return proxy;
}
reactive
的核心实现依赖于 ES6 的 Proxy
对象。Proxy
可以拦截对目标对象的操作,从而实现响应式。
baseHandlers
和 collectionHandlers
是两种不同的 Proxy
处理器,分别用于处理普通对象和集合类型(如 Map
、Set
等)。
baseHandlers
是用于普通对象的处理器,其源码位于 packages/reactivity/src/baseHandlers.ts
文件中。主要逻辑如下:
export const mutableHandlers: ProxyHandler<object> = {
get(target: Target, key: string | symbol, receiver: object) {
// 依赖收集
track(target, key);
// 返回属性值
return Reflect.get(target, key, receiver);
},
set(target: Target, key: string | symbol, value: any, receiver: object) {
// 触发更新
const result = Reflect.set(target, key, value, receiver);
trigger(target, key);
return result;
},
// 其他拦截操作...
};
collectionHandlers
是用于集合类型的处理器,其源码位于 packages/reactivity/src/collectionHandlers.ts
文件中。主要逻辑如下:
export const mutableCollectionHandlers: ProxyHandler<CollectionTypes> = {
get(target: CollectionTypes, key: string | symbol, receiver: object) {
// 依赖收集
track(target, key);
// 返回属性值
return Reflect.get(target, key, receiver);
},
// 其他拦截操作...
};
Vue3 的响应式系统通过 track
和 trigger
函数实现依赖收集和更新。
track
函数用于在访问响应式对象的属性时,收集当前的依赖。其源码如下:
export function track(target: object, key: unknown) {
if (!shouldTrack || activeEffect === undefined) {
return;
}
// 获取 target 对应的依赖映射
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
// 获取 key 对应的依赖集合
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
// 将当前的 effect 添加到依赖集合中
if (!dep.has(activeEffect)) {
dep.add(activeEffect);
activeEffect.deps.push(dep);
}
}
trigger
函数用于在修改响应式对象的属性时,触发依赖更新。其源码如下:
export function trigger(target: object, key: unknown) {
// 获取 target 对应的依赖映射
const depsMap = targetMap.get(target);
if (!depsMap) {
return;
}
// 获取 key 对应的依赖集合
const dep = depsMap.get(key);
if (dep) {
// 触发依赖更新
dep.forEach((effect) => {
if (effect !== activeEffect) {
effect.run();
}
});
}
}
通过以上分析,我们可以看到 reactive
的核心实现依赖于 Proxy
和 track
/trigger
机制。Proxy
用于拦截对目标对象的操作,而 track
和 trigger
则分别用于依赖收集和更新。这种设计使得 Vue3 的响应式系统更加高效和灵活。
理解 reactive
的源码实现,不仅有助于我们更好地使用 Vue3,还能为我们设计和实现类似的响应式系统提供宝贵的参考。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。