Vue 雙向綁定實(shí)現(xiàn)

vue2通過(guò) Object.defineProperty
vue3 通過(guò) Proxy
核心代碼Vue2
/**
 * 觀察某個(gè)對(duì)象的所有屬性
 * @param {Object} obj
 */
function observe(obj) {
  for (const key in obj) {
    // 循環(huán)為每一個(gè)對(duì)象屬性添加get set 方法
    let internalValue = obj[key];
    let funcs = [];
    Object.defineProperty(obj, key, {
      get: function () {
        //  依賴(lài)收集,記錄:是哪個(gè)函數(shù)在用我
        if (window.__func && !funcs.includes(window.__func)) {
          funcs.push(window.__func);
        }
        return internalValue;
      },
      set: function (val) {
        internalValue = val;
        // 派發(fā)更新,運(yùn)行:執(zhí)行用我的函數(shù)
        for (var i = 0; i < funcs.length; i++) {
          funcs[i]();
        }
      },
    });
  }
}

function autorun(fn) {
  window.__func = fn;
  fn();
  window.__func = null;
}
Vue3
/**
 * 觀察某個(gè)對(duì)象的所有屬性
 * @param {Object} obj
 */
function observe(obj) {
  let funcs = {};
  return new Proxy(obj, {
    get: function (obj, key) {
      //  依賴(lài)收集,記錄:是哪個(gè)函數(shù)在用我
      !funcs[key] && (funcs[key] = []);
      if (window.__func && !funcs[key].includes(window.__func)) {
        funcs[key].push(window.__func);
      }
      return obj[key];
    },
    set: function (obj, key, val) {
      obj[key] = val;
      // 派發(fā)更新,運(yùn)行:執(zhí)行用我的函數(shù)
      for (var i = 0; i < funcs[key].length; i++) {
        funcs[key][i]();
      }
      return obj[key];
    },
  });
}

function autorun(fn) {
  window.__func = fn;
  fn();
  window.__func = null;
}
完整例子
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <link rel="stylesheet" href="./index.css" />
  </head>
  <body>
    <div class="card">
      <p id="firstName"></p>
      <p id="lastName"></p>
      <p id="age"></p>
    </div>
    <input type="text" oninput="user.name = this.value" />
    <input type="date" onchange="user.birth = this.value" />
    <script src="./euv.js"></script>
    <script src="./index.js"></script>
  </body>
</html>
var user = {
  name: '克勞德',
  birth: '1997-5-25',
};

observe(user); // 觀察

// 顯示姓氏
function showFirstName() {
  document.querySelector('#firstName').textContent = '姓:' + user.name[0];
}

// 顯示名字
function showLastName() {
  document.querySelector('#lastName').textContent = '名:' + user.name.slice(1);
}

// 顯示年齡
function showAge() {
  var birthday = new Date(user.birth);
  var today = new Date();
  today.setHours(0), today.setMinutes(0), today.setMilliseconds(0);
  thisYearBirthday = new Date(
    today.getFullYear(),
    birthday.getMonth(),
    birthday.getDate()
  );
  var age = today.getFullYear() - birthday.getFullYear();
  if (today.getTime() < thisYearBirthday.getTime()) {
    age--;
  }
  document.querySelector('#age').textContent = '年齡:' + age;
}
autorun(showFirstName);
autorun(showLastName);
autorun(showAge);

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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