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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。