36.響應(yīng)式原理

手寫響應(yīng)式原理-vue3

let activeReactiveFn = null;
class Depend {
  constructor() {
    this.reactiveFns = new Set();
  }
  depend() {
    if (activeReactiveFn) {
      this.reactiveFns.add(activeReactiveFn);
    }
  }
  notify() {
    this.reactiveFns.forEach((fn) => fn());
  }
}

const targetMap = new WeakMap();
const getDepend = (target, key) => {
  let map = targetMap.get(target);
  if (!map) {
    map = new Map();
    targetMap.set(target, map);
  }

  let depend = map.get(key);
  if (!depend) {
    depend = new Depend();
    map.set(key, depend);
  }
  return depend;
};

const watchEffect = (fn) => {
  activeReactiveFn = fn;
  fn(); //執(zhí)行函數(shù)并收集依賴
  activeReactiveFn = null;
};

//傳入一個(gè)普通對(duì)象,返回一個(gè)Proxy代理對(duì)象
const reactive = (obj) => {
  return new Proxy(obj, {
    //監(jiān)聽獲取對(duì)象的屬性值
    get(target, key, receiver) {
      const depend = getDepend(target, key);
      depend.depend();
      return Reflect.get(target, key, receiver);
    },

    //監(jiān)聽設(shè)置對(duì)象的屬性值
    set(target, key, newVal, receiver) {
      Reflect.set(target, key, newVal, receiver);
      const depend = getDepend(target, key);
      depend.notify();
    },
  });
};
const obj = reactive({
  name: "why",
  age: 18,
});
const info =reactive({
  name: 'koby'
})

//收集每一個(gè)依賴obj.name的函數(shù)
watchEffect(() => {
  const newName = obj.name;
  console.log(newName);
});

watchEffect(() => {
  console.log(obj.name);
  console.log(obj.age);
});

watchEffect(() => {
  console.log(obj.age);
});
watchEffect(() => {
  console.log(info.name);
});

//當(dāng)obj.name的值發(fā)生改變,所有包含依賴obj.name的代碼塊的函數(shù)都重新執(zhí)行
obj.name = "lily";

手寫響應(yīng)式原理-vue2

let activeReactiveFn = null;
class Depend {
  constructor() {
    this.reactiveFns = new Set();
  }
  depend() {
    if (activeReactiveFn) {
      this.reactiveFns.add(activeReactiveFn);
    }
  }
  notify() {
    this.reactiveFns.forEach((fn) => fn());
  }
}

const targetMap = new WeakMap();
const getDepend = (target, key) => {
  let map = targetMap.get(target);
  if (!map) {
    map = new Map();
    targetMap.set(target, map);
  }

  let depend = map.get(key);
  if (!depend) {
    depend = new Depend();
    map.set(key, depend);
  }
  return depend;
};

const watchEffect = (fn) => {
  activeReactiveFn = fn;
  fn(); //執(zhí)行函數(shù)并收集依賴
  activeReactiveFn = null;
};

//傳入一個(gè)普通對(duì)象,返回一個(gè)Proxy代理對(duì)象
const reactive = (obj) => {
  Object.keys(obj).forEach((key) => {
    const value = obj[key];
    Object.defineProperty(obj, key, {
      get() {
        const depend = getDepend(obj, key);
        depend.depend();
        return value;
      },
      set(newVal) {
        value = newVal;
        const depend = getDepend(obj, key);
        depend.notify();
      },
    });
  });
  return obj;
};
const obj = reactive({
  name: "why",
  age: 18,
});
const info = reactive({
  name: "koby",
});

//收集每一個(gè)依賴obj.name的函數(shù)
watchEffect(() => {
  const newName = obj.name;
  console.log(newName);
});

watchEffect(() => {
  console.log(obj.name);
  console.log(obj.age);
});

watchEffect(() => {
  console.log(obj.age);
});
watchEffect(() => {
  console.log(info.name);
});

//當(dāng)obj.name的值發(fā)生改變,所有包含依賴obj.name的代碼塊的函數(shù)都重新執(zhí)行
obj.name = "lily";

非常感謝王紅元老師的深入JavaScript高級(jí)語法讓我學(xué)習(xí)到很多 JavaScript 的知識(shí)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容