學(xué)習(xí)記錄02:提高大型數(shù)據(jù)列表的性能

通常我們?cè)趹?yīng)用中會(huì)請(qǐng)求一些列表數(shù)據(jù),比如說(shuō)用戶(hù)列表、商品列表、文章列表等等......

而且有時(shí)候,我們并不會(huì)去修改這些請(qǐng)求回來(lái)的列表數(shù)據(jù),而只是單純地去展示它們,或者是把它們保存在全局狀態(tài)管理器里面(又稱(chēng)之為 Vuex)。請(qǐng)求數(shù)據(jù)列表的示意代碼如下所示:

export default {

? data: () => ({

? ? users: {}

? }),

? async created() {

? ? const users = await axios.get("/api/users");

? ? this.users = users;

? }

};

Vue 在默認(rèn)情況下,會(huì)將數(shù)組this.users中的,所有對(duì)象的第一層屬性設(shè)置為響應(yīng)式數(shù)據(jù)。

這對(duì)于大型的對(duì)象數(shù)組來(lái)說(shuō),性能成本非常的高。沒(méi)錯(cuò),的確有時(shí)候列表數(shù)據(jù)是有分頁(yè)的,但總會(huì)有一些情況下,是沒(méi)有進(jìn)行分頁(yè),繼而在前端展示的。

一個(gè)實(shí)際的例子就是谷歌地圖的標(biāo)記點(diǎn) markers 列表數(shù)據(jù),這就是一個(gè)擁有很多對(duì)象的大型數(shù)組。

所以,在一些特定的情況下,如果我們能夠阻止 Vue 將這些列表數(shù)據(jù)設(shè)置為響應(yīng)式的,那么我們就可以為項(xiàng)目帶來(lái)一些性能上的提升。實(shí)際上我們就是可以做到的,通過(guò)用Object.freeze方法,將獲取到的列表數(shù)據(jù)在賦值給組件之前,進(jìn)行凍結(jié):

export default {

? data: () => ({

? ? users: {}

? }),

? async created() {

? ? const users = await axios.get("/api/users");

? ? this.users = Object.freeze(users);

? }

};

記住,同樣地可以應(yīng)用到 Vuex 實(shí)踐中:

const mutations = {

? setUsers(state, users) {

? ? state.users = Object.freeze(users);

? }

};

順便說(shuō)一下,如果你確實(shí)有需要去修改請(qǐng)求得到的列表數(shù)據(jù),那么你仍然可以通過(guò)創(chuàng)建一個(gè)新的數(shù)組來(lái)實(shí)現(xiàn)。舉個(gè)例子,給原列表數(shù)據(jù)添加一個(gè)同類(lèi)型元素,可以這么操作:

state.users = Object.freeze([...state.users, user]);

來(lái)源:https://juejin.cn/post/6844903766982934535

來(lái)深究一下為什么Object.freeze()方法可以做到阻止Vue添加雙向數(shù)據(jù)綁定機(jī)制

大家應(yīng)該都知道Vue是通過(guò)Object.defineProperty()來(lái)修改屬性描述符中的setter和getter的,在getter中收集依賴(lài),在setter的時(shí)候觸發(fā)依賴(lài)。

在ES5開(kāi)始,所有的屬性都有了屬性描述符。決定是否可以修改一個(gè)屬性的描述符有兩個(gè):

是Writable:決定是否可以修改屬性的值;

另一個(gè)是Configurable:決定是否可以使用Object.defineProperty()來(lái)修改屬性描述符,并且也會(huì)禁止刪除這個(gè)屬性;

當(dāng)這兩個(gè)描述符同時(shí)為false時(shí),意味著這個(gè)屬性完全是一個(gè)常量,Vue不能通過(guò)Object.defineProperty()來(lái)添加雙向數(shù)據(jù)綁定。收集不了依賴(lài),也就做不了雙向數(shù)據(jù)綁定,就少添加很多watcher實(shí)例。

執(zhí)行Object.freeze()會(huì)執(zhí)行Object.seal()并吧所有的屬性的writable設(shè)置成false。

Object.seal()則會(huì)調(diào)用Object.preventExtensions()并把configurable設(shè)為false。

Object.preventExtensions()則會(huì)禁止對(duì)象添加新的屬性。

最后還有一個(gè)疑問(wèn),state.users = Object.freeze([...state.users, user]);會(huì)不會(huì)觸發(fā)視圖更新。

答案是會(huì)。users變量是定義在data中的,在Vue初始化initState的時(shí)候,會(huì)遍歷data中的所有屬性,添加監(jiān)聽(tīng)。也就是說(shuō)我們凍結(jié)的是users里面所有的屬性,并沒(méi)有凍結(jié)Vue中data,所以替換users會(huì)觸發(fā)雙向數(shù)據(jù)綁定

來(lái)源:http://www.itdecent.cn/p/56168a779849

最后編輯于
?著作權(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)容