欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue2和Vue3的雙向數(shù)據(jù)綁定原理分析

 更新時間:2025年02月06日 09:47:43   作者:清風 與我  
Vue2.x通過Object.defineProperty()實現(xiàn)響應(yīng)式系統(tǒng),但存在一些限制,如不能檢測新增和刪除的屬性、深層嵌套對象性能開銷大等,Vue3.0引入Proxy,可以更高效地攔截對象操作,解決這些問題

vue2.x 是如何實現(xiàn)響應(yīng)式系統(tǒng)的

當你把一個普通的 js 對象傳入 vue 實例作為 data 選項,vue 將遍歷此對象的所有prototype(屬性),并使用 object.defineProperty(),將這些 prototype(屬性),全部轉(zhuǎn)換為 getter / setter,在 getter 中收集數(shù)據(jù)依賴,在 setter 中監(jiān)聽數(shù)據(jù)變化,一旦數(shù)據(jù)發(fā)生改變,在通知訂閱者。

每個組件實例,都對應(yīng)一個 watcher 實例,它會在組件渲染的過程把 “接觸” 過的數(shù)據(jù) prototype(屬性)記錄為依賴,之后當依賴項的 setter 觸發(fā)時,會通知 watcher,從而使它關(guān)聯(lián)的組件重新渲染;

defineProperty 的痛點

  1. 它無法發(fā)現(xiàn)對象新增和被刪除的屬性,當你給一個對象添加一個新的屬性,這個新增的屬性沒有添加到 vue 的數(shù)據(jù)更新偵查機制里;

Vue.set() 可以讓 vue 知道你新增了一個屬性,其實 Vue.set 可以讓 Vue 知道新增了一個屬性。其實 set() 內(nèi)部也是通過調(diào)用 defineProperty() 來實現(xiàn);

  1. 當你利用索引直接設(shè)置一個數(shù)組(new Array(4))或者修改數(shù)組的長度時,Vue 不能檢測到數(shù)組的變動;
  2. 當對象嵌套的層數(shù)特別深(多層嵌套)的時候,遞歸遍歷帶來的性能開銷就會比較大;

Object.defineProperty 代碼的使用

mounted() {
    // 先定義好一套規(guī)則
    class Observer {
      constructor(data) {
        for (let key of Object.keys(data)) {
          if (typeof data[key] === "object") {
            data[key] = new Observer(data[key]);
          }
          Object.defineProperty(this, key, {
            enumerable: true,
            configurable: true,
            get() {
              console.log("You visited" + key);
              return data[key];
            },
            set(NewValue) {
              console.log("You set" + key);
              console.log("New Value" + NewValue);
              if (NewValue === data[key]) {
                return;
              }
              data[key] = NewValue;
            },
          });
        }
      }
    }
    let obj = {
      name: "app",
      age: 18,
      a: {
        b: 1,
        c: {
          d: 1,
        },
      },
    };
    let app = new Observer(obj);
    console.log(app);
    app.age = 20;
    app.newProperty = "new attrs";
    console.log(app);
  },

結(jié)果:

Proxy 方法的理解

Proxy 在 vue3.0 中上位

可以解決 defineProperty 的痛點,因為本質(zhì)的原因在于 Proxy 是內(nèi)置了攔截器對象。所有的外部訪問都得先經(jīng)過這一層攔截,不管是先前定義好的,還是新增的屬性,又或者是深層的嵌套屬性,訪問時都會被攔截;

Reflect.set()方法用于設(shè)置對象屬性的值,1:目標對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值:4:值是this如果遇到設(shè)置器,將提供給目標調(diào)用。

此方法返回一個布爾值,該值指示該屬性是否已成功設(shè)置。

Proxy 代碼的使用

mounted() {
    const obj = {
      name: "app",
      age: 19,
      a: {
        b: 1,
        c: 2,
      },
    };
    const p = new Proxy(obj, {
      get(target, propKey, receiver) {
        console.log("Your visited:" + propKey);
        // Reflect.set()方法用于設(shè)置對象屬性的值:1:目標對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值
        // 此方法返回一個布爾值,該值指示該屬性是否已成功設(shè)置。
        return Reflect.set(target, propKey, receiver);
      },
      set(target, propKey, value, receiver) {
        console.log("You set:" + propKey);
        console.log("New value:" + value);
        // Reflect.set()方法用于設(shè)置對象屬性的值,1:目標對象:2:改變參數(shù)的名稱:3:改變參數(shù)的值:4:值是this如果遇到設(shè)置器,將提供給目標調(diào)用。
        // 此方法返回一個布爾值,該值指示該屬性是否已成功設(shè)置。
        return Reflect.set(target, propKey, value, receiver);
      },
    });
    p.age = "20";
    console.log(p);
    p.newProperty = "New attribute";
    console.log(p);
  },

結(jié)果:

總結(jié)

  1. proxy 是用來操作對象并且擴展對象能到,而 Object.defineProperty() 只是單純的操作對象的屬性;
  2. Vue2.X 是用 Object.defineProperty() 實現(xiàn)數(shù)據(jù)響應(yīng)的,但是受限于 defineProperty() 的實現(xiàn),必須遞歸遍歷至對象的最底層;
  3. vue3.0 用 Proxy 來攔截對象,不管對目標執(zhí)行任何操作,都會先通過 Proxy 的處理邏輯;
  4. 除了 Vue3.0,還有其他的庫也在使用 Proxy。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue路由跳轉(zhuǎn)的4種方式小結(jié)

    Vue路由跳轉(zhuǎn)的4種方式小結(jié)

    本文主要介紹了Vue路由跳轉(zhuǎn)的4種方式小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-06-06
  • vue點擊標簽切換選中及互相排斥操作

    vue點擊標簽切換選中及互相排斥操作

    這篇文章主要介紹了vue點擊標簽切換選中及互相排斥操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • 如何修改vant的less樣式變量

    如何修改vant的less樣式變量

    這篇文章主要介紹了如何修改vant的less樣式變量方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • vue elementUI Plus實現(xiàn)拖拽流程圖的詳細代碼(不引入插件)

    vue elementUI Plus實現(xiàn)拖拽流程圖的詳細代碼(不引入插件)

    文章介紹了如何使用Vue和elementUI Plus實現(xiàn)一個簡單的拖拽流程圖功能,不引入任何插件,完全手寫,設(shè)計思路,感興趣的朋友跟隨小編一起看看吧
    2025-01-01
  • vue實現(xiàn)給某個數(shù)據(jù)字段添加顏色

    vue實現(xiàn)給某個數(shù)據(jù)字段添加顏色

    這篇文章主要介紹了vue實現(xiàn)給某個數(shù)據(jù)字段添加顏色方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • VUE配置history路由模式配置詳細舉例

    VUE配置history路由模式配置詳細舉例

    這篇文章主要給大家介紹了關(guān)于VUE配置history路由模式配置的相關(guān)資料,History模式是Vue路由的另一種模式,在History模式下URL中的路徑不再使用#符號,而是直接使用正常的路徑形式,需要的朋友可以參考下
    2023-12-12
  • Vue中路由參數(shù)與查詢參數(shù)傳遞對比解析

    Vue中路由參數(shù)與查詢參數(shù)傳遞對比解析

    在Vue.js中,路由與導航不僅涉及頁面切換,還包括了向頁面?zhèn)鬟f參數(shù)和獲取查詢參數(shù),這篇文章主要介紹了Vue路由參數(shù)與查詢參數(shù)傳遞,需要的朋友可以參考下
    2023-08-08
  • Vue?如何關(guān)掉響應(yīng)式問題

    Vue?如何關(guān)掉響應(yīng)式問題

    這篇文章主要介紹了Vue?如何關(guān)掉響應(yīng)式問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue router點擊打開新的標簽頁的方法(最新推薦)

    vue router點擊打開新的標簽頁的方法(最新推薦)

    vue router點擊打開新的標簽頁的方法,只需要在router-link中加入target="_blank"即可在新的頁面打開標簽,本文通過實例代碼給大家介紹的非常詳細,需要的朋友參考下吧
    2023-10-10
  • Vue項目安裝使用moment.js方式

    Vue項目安裝使用moment.js方式

    文章介紹了如何在Vue項目中安裝和使用moment.js,包括安裝步驟、導入方法、漢化設(shè)置以及在Vue實例中使用moment.js進行日期處理
    2024-11-11

最新評論