vue3原始碼學習之reactive實現

shellingfordly發表於2022-04-13

vue3 原始碼

最近崔哥的mini-vue十分火啊,已經飆到5.9k的star了。

看來大家都很卷,我也不能落後,這是我學習之後實現的mini-vue,包含了mini-vue程式碼的實現,學習筆記和一些思考。

後續我會持續更新學習筆記和思維導圖,目前寫了reactive,畫了effect的思維導圖。

reactive 思維導圖

image.png

createReactiveObject

建立響應式物件
  • 引數

    • target 目標物件
    • proxyMap 快取 map
    • baseHandlers 處理物件
  • 步驟

    • 獲取已經存在的代理物件,效能優化
    • 建立代理物件,設定快取
function createReactiveObject(target, proxyMap, baseHandlers) {
  const existingProxy = proxyMap.get(taget);

  // 使用快取優化
  if (existingProxy) {
    return existingProxy;
  }

  const proxy = new Proxy(taget, baseHandlers);
  proxyMap.set(taget, proxy);

  return proxy;
}

baseHandlers

  1. mutableHandlers
reactive 的處理物件,非只讀 isReadonly = false,非淺響應 shallow = false
const get = createGetter();
const set = createSetter();

export const mutableHandlers = {
  get,
  set,
};
  1. readonlyHandlers
readonly 的處理物件,只讀 isReadonly = true,非淺響應 shallow = false
const readonlyGet = createGetter(true);

export const readonlyHandlers = {
  get: readonlyGet,
  set(target, key) {
    // 不能更改
    console.warn(`${target} of ${key} can't be setted, it's a readonly object`);
    return true;
  },
};
  1. shallowReadonlyHandlers
shallowReadonly 的處理物件,只讀 isReadonly = true,淺響應 shallow = true,set 與 readonlyHandlers 一致
const shallowReadonlyGet = createGetter(true, true);

export const shallowReadonlyHandlers = Object.assign({}, readonlyHandlers, {
  get: shallowReadonlyGet,
});

createGetter

生成 get 函式
function createGetter(isReadonly = false, shallow = false) {
  return (target, key, receiver) => {
    if (key === ReactiveFlags.IS_REACTIVE) {
      // 判斷是否為 readonly 物件
      return !isReadonly;
    } else if (key === ReactiveFlags.IS_READONLY) {
      // 判斷是否為 reactive 物件
      return isReadonly;
    }

    // 如果不是隻讀物件,收集依賴
    // 只讀物件不能更改,所以不需要收集
    if (!isReadonly) {
      track(target, "get", key);
    }

    // 獲取屬性值
    const res = Reflect.get(target, key, receiver);

    // 只對最外層最響應式,不執行巢狀物件的響應式轉換
    if (shallow) {
      return res;
    }

    // 執行巢狀物件的響應式轉換
    if (isObjectOrArray(res)) {
      return isReadonly ? readonly(res) : reactive(res);
    }
    return res;
  };
}

createSetter

生成 set 函式
function createSetter() {
  return (target, key, value, receiver) => {
    // 設定屬性值
    const res = Reflect.set(target, key, value, receiver);

    // 觸發 依賴
    trigger(target, "set", key);
    return res;
  };
}

工具函式

  • isProxy 判斷是否是 reactive 或者 readonly 型別
  • isReactive 是否是 reactive 型別
  • isReadonly 是否是 readonly 型別

相關文章