91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

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

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

Vue3的響應式原理是什么

發布時間:2022-08-12 11:18:06 來源:億速云 閱讀:136 作者:iii 欄目:開發技術

這篇文章主要介紹“Vue3的響應式原理是什么”,在日常操作中,相信很多人在Vue3的響應式原理是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue3的響應式原理是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

Proxy

Vue3 的響應式原理依賴了 Proxy 這個核心 API,通過 Proxy 可以劫持對象的某些操作。

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

p.a; // 輸出 --> get
p.a = 2; // 輸出 --> set
"a" in p; // 輸出 --> has
delete p.a; // 輸出 --> deleteProperty

如上例子,我們用 Proxy 代理了 Obj 對象的屬性訪問、屬性賦值、in 操作符、delete 的操作,并進行 console.log 輸出。

Reflect

Reflect 是與 Proxy 搭配使用的一個 API,當我們劫持了某些操作時,如果需要再把這些操作反射回去,那么就需要 Reflect 這個 API。

由于我們攔截了對象的操作,所以這些操作該有的功能都喪失了,例如,訪問屬性 p.a 應該得到 a 屬性的值,但此時卻不會有任何結果,如果我們還想擁有攔截之前的功能,那我們就需要用 Reflect 反射回去。

const obj = { a: 1 };
const p = new Proxy(obj, {
  get(target, property, receiver) {
    console.log("get");
    return Reflect.get(target, property, receiver);
  },
  set(target, property, value, receiver) {
    console.log("set");
    return Reflect.set(target, property, receiver);
  },
  has(target, prop) {
    console.log("has");
    return Reflect.has(target, prop);
  },
  deleteProperty(target, prop) {
    console.log("deleteProperty");
    return Reflect.deleteProperty(target, prop);
  },
});

舉個例子

以下全文我們都會通過這個例子來講述 Vue3 響應式的原理。

<div id="app"></div>

<script>
  // 創建一個響應式對象
  const state = reactive({ counter: 1 });

  // 立即運行一個函數,當響應式對象的屬性發生改變時重新執行。
  effect(() => {
    document.querySelector("#app").innerHTML = state.counter;
  });

  // 2s 后視圖更新
  setTimeout(() => {
    state.counter += 1;
  }, 2000);
</script>

我們用 reactive 創建了一個響應式對象 state,并調用了 effect 方法,該方法接受一個副作用函數,effect 的執行會立即調用副作用函數,并將 state.counter 賦值給 #app.innerHTML;兩秒后,state.counter += 1,此時,effect 的副作用函數會重新執行,頁面也會變成 2.

內部的執行過程大概如下圖所示:

Vue3的響應式原理是什么

  • 調用 reactive() 返回一個 Proxy 代理對象,并劫持對象的 get 與 set 操作

  • 調用 effect() 方法時,會訪問屬性 state.counter,此時會觸發 proxy 的 get 操作。

  • get 方法會調用 track() 進行依賴收集;建立一個對象(state)、屬性(counter)、effect 副作用函數的依賴關系;

  • set 方法會調用 trigger() 進行依賴更新;通過對象(state)與屬性(coutner)找到對應的 effect 副作用函數,然后重新執行。

reactive

reactive 會返回如下一個 Proxy 對象

const reactive = (target) => {
  return new Proxy(target, {
    get(target, key, receiver) {
      const res = Reflect.get(target, key, receiver);

      track(target, key); // 收集依賴

      if (isObject(res)) {
        // 如果當前獲取的屬性值是一個對象,則繼續將為此對象創建 Proxy 代理
        return reactive(res);
      }

      return res;
    },

    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 依賴更新
    },
  });
};

effect

let activeEffect;
function effect(fn) {
  const _effect = function reactiveEffect() {
    activeEffect = _effect;
    fn();
  };

  _effect();
}

首先定義全局的 activeEffect,它永遠指向當前正在執行的 effect 副作用函數。effect 為 fn 創建一個內部的副作用函數,然后立即執行,此時會觸發對象的 get 操作,調用 track() 方法。

effect(() => {
  // effect 的立即執行會訪問 state.counter,觸發了對象的 get 操作。
  document.querySelector("#app").innerHTML = state.counter;
});

track

track 會建立一個 對象(state) => 屬性(counter) => effect 的一個依賴關系

const targetMap = new WeakMap();
function track(target, key) {
  if (!activeEffect) {
    return;
  }

  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }

  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }

  if (!dep.has(activeEffect)) {
    dep.add(activeEffect);
  }
}

執行完成成后我們得到一個如下的數據結構:

[ // map 集合
  {
    key: {counter: 1} // state 對象,
    value: [ // map 集合
      {
        key: "counter",
        value: [ // set
          function reactiveEffect() {} // effect 副作用函數
        ],
      }
    ],
  },
];

注意:當我們調用 effect 時,會將當前的副作用函數賦值給全局的 activeEffect,所以此時我們可以正確關聯其依賴。

trigger

當我們給 state.counter 賦值的時候就會觸發代理對象的 set 操作,從而調用 trigger 方法

setTimeout(() => {
  // 給 counter 屬性賦值會觸發 set 操作
  state.counter += 1;
}, 2000);
function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;

  const effects = depsMap.get(key);
  effects && effects.forEach((effect) => effect());
}

到此,關于“Vue3的響應式原理是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

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

AI

微博| 大英县| 德安县| 蓬安县| 鹿泉市| 唐河县| 汾阳市| 津南区| 广河县| 北碚区| 台北县| 云南省| 永定县| 扎赉特旗| 滨海县| 保定市| 宕昌县| 万安县| 积石山| 威远县| 宁蒗| 巴南区| 景泰县| 鄢陵县| 新龙县| 麦盖提县| 莆田市| 抚州市| 津市市| 芒康县| 皋兰县| 石林| 嘉黎县| 丹巴县| 永泰县| 大宁县| 沧州市| 嵩明县| 蒙山县| 静安区| 洛川县|