Object.freeze()提升Vue.js中大型列表的性能【翻譯+解讀】

介紹

文章連接:vuedose.tips/tips/improv…
這個網站主打,簡潔快速的分享一些關於Vue的tips。每週更新,會發到郵件上。正文是翻譯,解讀是我本身的相關理解。vue

正文

在開發過程當中,咱們常常須要獲取一些對象,像users信息,列表items,文章信息等等,可是咱們不須要去修改這些信息。咱們只是把這些信息展現出來,或者放在vuexstate裏面。以下代碼所示ios

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = users;
  }
};
複製代碼

Vue默認會對每一個數組數據的每一層屬性,添加雙向數據綁定機制。當數組對象很是龐大時,消耗在這上面的雙向數據綁定就越多。 由於,在這種場景下,咱們能夠經過阻止Vue對這些數據添加雙向數據綁定來提升一些性能。Object.freeze()就能作到這點。vuex

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};
複製代碼

記住在Vuex中也可這樣使用axios

const mutations = {
  setUsers(state, users) {
    state.users = Object.freeze(users);
  }
};
複製代碼

若是你須要改變這些信息,你能夠建立一個新的被凍結的數組並賦值給他api

state.users = Object.freeze([...state.users, user]);
複製代碼

解讀

來深究一下爲何Object.freeze()方法能夠作到阻止Vue添加雙向數據綁定機制

你們應該都知道Vue是經過Object.defineProperty()來修改屬性描述符中的settergetter的,在getter中收集依賴,在setter的時候觸發依賴。
在ES5開始,全部的屬性都有了屬性描述符。決定是否能夠修改一個屬性的描述符有兩個:數組

  • Writable:決定是否能夠修改屬性的值;
  • 另外一個是Configurable:決定是否可使用Object.defineProperty()來修改屬性描述符,而且也會禁止刪除這個屬性;

當這兩個描述符同時爲false時,意味着這個屬性徹底是一個常量,Vue不能經過Object.defineProperty()來添加雙向數據綁定。收集不了依賴,也就作不了雙向數據綁定,就少添加不少watcher實例。
async

  • 執行Object.freeze()會執行Object.seal()並吧全部的屬性的writable設置成false
  • Object.seal()則會調用Object.preventExtensions()並把configurable設爲false
  • Object.preventExtensions()則會禁止對象添加新的屬性。
    這一趟下來,基本上變成一個永久性不能加查刪的對象了。我作了個草圖,你們康康,幫助理解下。

最後還有一個疑問,state.users = Object.freeze([...state.users, user]);會不會觸發視圖更新。

答案是會。我親自寫demo測試過,從新賦值會觸發更新。
是爲何呢?
其實很簡單,users變量是定義在data中的,在Vue初始化initState的時候,會遍歷data中的全部屬性,添加監聽。也就是說咱們凍結的是users裏面全部的屬性,並無凍結Vue中data,因此替換users會觸發雙向數據綁定。性能

翻譯或者理解有紕漏的,歡迎你們幫忙指正~測試

相關文章
相關標籤/搜索