溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue3響應式核心之reactive源碼分析

發布時間:2023-04-25 15:41:18 來源:億速云 閱讀:164 作者:iii 欄目:開發技術

Vue3響應式核心之reactive源碼分析

Vue3 的響應式系統是其核心特性之一,而 reactive 是 Vue3 中用于創建響應式對象的核心 API。本文將深入分析 reactive 的源碼實現,幫助讀者更好地理解 Vue3 的響應式機制。

1. reactive 的基本用法

在 Vue3 中,reactive 函數用于將一個普通對象轉換為響應式對象。響應式對象的屬性在被訪問或修改時,會自動觸發依賴收集和更新。

import { reactive } from 'vue';

const state = reactive({
  count: 0,
});

state.count++; // 觸發更新

2. reactive 的源碼結構

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
  );
}

2.1 createReactiveObject 函數

createReactiveObjectreactive 的核心實現函數,負責創建響應式對象。其源碼如下:

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;
}

2.2 Proxy 和 Handlers

reactive 的核心實現依賴于 ES6 的 Proxy 對象。Proxy 可以攔截對目標對象的操作,從而實現響應式。

baseHandlerscollectionHandlers 是兩種不同的 Proxy 處理器,分別用于處理普通對象和集合類型(如 Map、Set 等)。

2.2.1 baseHandlers

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;
  },
  // 其他攔截操作...
};

2.2.2 collectionHandlers

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);
  },
  // 其他攔截操作...
};

3. 依賴收集與更新

Vue3 的響應式系統通過 tracktrigger 函數實現依賴收集和更新。

3.1 track 函數

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);
  }
}

3.2 trigger 函數

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();
      }
    });
  }
}

4. 總結

通過以上分析,我們可以看到 reactive 的核心實現依賴于 Proxytrack/trigger 機制。Proxy 用于攔截對目標對象的操作,而 tracktrigger 則分別用于依賴收集和更新。這種設計使得 Vue3 的響應式系統更加高效和靈活。

理解 reactive 的源碼實現,不僅有助于我們更好地使用 Vue3,還能為我們設計和實現類似的響應式系統提供寶貴的參考。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女