摘要:不要小看這個(gè)優(yōu)化,由于內(nèi)部監(jiān)聽器中的比例很高超過所以在的情況下,可以帶來比較大的提升。但是它的時(shí)間復(fù)雜度是,在大列表下會(huì)帶來顯著的性能開銷甚至完全超過更新的開銷。更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)分享請(qǐng)?jiān)L問網(wǎng)易云社區(qū)。文章來源網(wǎng)易云社區(qū)
本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。
本文旨在用 20% 的精力解決使用Regular過程中 80% 的性能問題.
這里大部分是關(guān)于臟檢查的性能優(yōu)化,不了解的可以先看下《Regular臟檢查介紹》
首先,我們可以用一個(gè)簡(jiǎn)化后的公式來描述Regular的單次臟檢查的復(fù)雜度
N·logN · M · T
其中
N : 代表組件深度
M : 代表組件平均監(jiān)聽器數(shù)量
T : 代表單個(gè)Watcher的檢查時(shí)間
這樣問題就落在了如何降低這三個(gè)因子了
降低N —— 組件層級(jí)
這層是收益最高的方案,因?yàn)橛绊懸蜃邮?N·logN.
以上圖為例,葉子節(jié)點(diǎn)進(jìn)行$update()時(shí),會(huì)首先找到DigestRoot (默認(rèn)情況下,即頂層使用 new 創(chuàng)建的組件),再層層向下進(jìn)行組件的$digest()檢查,在目前組件抽象較細(xì)致的開發(fā)習(xí)慣下,很容易產(chǎn)生10多層的組件深度,適當(dāng)控制下digest深度可以得到可觀的性能提升。
注 : 這個(gè)digest flow設(shè)計(jì)是為了避免產(chǎn)生網(wǎng)狀更新鏈
方案1. 使用isolate 控制digest深度
第一個(gè)方式即使用isolate屬性控制組件的數(shù)據(jù)流向,如 這樣,在第一次初始化后,b組件就不再與a組件有任何數(shù)據(jù)綁定關(guān)系
如圖所示,b組件此時(shí)就會(huì)成為g組件的實(shí)際DigestRoot。b組件內(nèi)部的$update不會(huì)再會(huì)冒泡到外層
但這種方式同時(shí)讓a的數(shù)據(jù)變更無法傳達(dá)到b組件極其內(nèi)部,如下圖所示
如果需要實(shí)現(xiàn)a->b的單向傳導(dǎo),可以設(shè)置isolate=1
isolate = 1 實(shí)際就形成了組件的單向數(shù)據(jù)流
方案2. 合理抽象組件
除了通過isolate手動(dòng)控制更新樹的深度之外,我們直接減小組件深度當(dāng)然也可以。 但這似乎與React等框架推崇的方式相悖,其實(shí)不然。
過度抽象的組件,除了引入使用負(fù)擔(dān)和增加組件層級(jí)外,無法帶來直觀的收益。 抽象記得要基于復(fù)用的前提,沒有復(fù)用前提的組件抽象,除了讓你的文件夾變得更復(fù)雜外,毫無益處。 當(dāng)然它可以給你帶來好看的組件結(jié)構(gòu)圖 :)
降低M: 平均監(jiān)聽者數(shù)量
在Dirty-Check Loop中,在每個(gè)組件節(jié)點(diǎn)上都會(huì)經(jīng)歷$digest階段: 遍歷監(jiān)聽者數(shù)組,檢查數(shù)據(jù)是否發(fā)生變更。
方案1. 升級(jí)到v0.5.2版本以上
首先將上面的公式再簡(jiǎn)化,并拓展到 一輪完整的臟檢查Dirty-Check Loop ,可以用下面的公式來表示
K·P·T
其中
K: 臟檢查穩(wěn)定性檢測(cè)輪數(shù) (1~30次不等,30次仍不穩(wěn)定將拋出錯(cuò)誤)
P:?digest影響到的所有監(jiān)聽器
T: 單個(gè)監(jiān)聽器的消耗時(shí)間
在Github: 0.5.2版本,有一個(gè)優(yōu)化就是講監(jiān)聽器分為了 穩(wěn)定監(jiān)聽器(stable) 和 不穩(wěn)定監(jiān)聽器(unstable)
不穩(wěn)定的監(jiān)聽器即具有Side Effect,比如
this.$watch("firstName", (firstName)=>{ this.data.nickname = firstName + "先生"})
當(dāng)firstName改變時(shí),nickname也會(huì)隨之改變,所以為了確保不出錯(cuò),框架會(huì)檢測(cè)多輪直到這類監(jiān)聽表達(dá)式不再變化
穩(wěn)定的監(jiān)聽器就是一些沒有Side Effect的監(jiān)聽比如大部分內(nèi)置的監(jiān)聽(文本插值、r-html、屬性插值等), 這類監(jiān)聽處理邏輯只有讀操作,而沒有寫操作。其實(shí)只需要檢測(cè)一次即可
這樣公式就修改為了
K·P1·T + P2·T
其中 P1+P2 = P , P2 為Stable監(jiān)聽器, P1為非穩(wěn)定。不要小看這個(gè)優(yōu)化,由于內(nèi)部監(jiān)聽器中, P2的比例很高(超過80%)所以在K>1的情況下,可以帶來比較大的提升。
除此之外,你同時(shí)也可以自己主動(dòng)來標(biāo)記哪個(gè)監(jiān)聽器是屬于stable
this.$watch("title", (title)=>{ this.$refs.top.innerText = title
}, {stable: true})
使用一次綁定表達(dá)式@(expression)
除非明確了不再對(duì)某個(gè)監(jiān)聽感興趣,通過 一次綁定表達(dá)式 來提升性能其實(shí)并不是特別關(guān)鍵,但如果這個(gè)表達(dá)式正好在一個(gè)list循環(huán)中,那控制的收益會(huì)比較大,比如
{#list list as item by item_index}
如果這個(gè)列表有100項(xiàng),那可以直接減少100個(gè)對(duì)item.list綁定(何況大部分情況都不止一個(gè)屬性傳入), 屬于操作少收益大。
降低T: 單個(gè)監(jiān)聽器的平均消耗時(shí)間
其實(shí)每個(gè)表達(dá)式比如user.firstName + "-" + user.lastName 需要判斷變化的開銷各不相同,我們只需要針對(duì)高開銷的監(jiān)聽器進(jìn)行控制即可達(dá)到效果。
盡可能帶上list語句的by描述
list是最容易產(chǎn)生性能瓶頸的部分,下面做下簡(jiǎn)單說明
默認(rèn)情況下,Regular使用的萊文斯坦編輯距離(Levenshtein Distance), 別被嚇到了,實(shí)際上wiki百科等資源上都有完成的偽代碼描述, 是個(gè)簡(jiǎn)單的常用算法。
它的優(yōu)點(diǎn)是,不需額外標(biāo)記,就可以找到盡可能少的步驟從一個(gè)字符串過渡到另一個(gè)(但并不保證相同值一定被保留), 數(shù)組同理. 這樣映射到框架內(nèi)部,就可以以盡可能少的步驟來變更DOM了,相信大家都知道DOM開銷很大了。
但是它的時(shí)間復(fù)雜度是O(n^2) ,在大列表下會(huì)帶來顯著的性能開銷, 甚至完全超過DOM更新的開銷。
所以在Regular v0.3的某個(gè)版本引入了by的用法, 例如
{#list items as item by item_index}
{/list}
顧名思義,新舊列表按順序其item_index是不會(huì)變化的,即0,1,2... . 所以列表更新時(shí),不會(huì)嘗試去銷毀重建,而是直接更新內(nèi)部的值. 這種更新方式,內(nèi)部的diff復(fù)雜度是 O(n), 屬于極大的優(yōu)化了性能.而且在DOM更新上比LS算法模式更輕量
這樣用by item_index其實(shí)也帶來一個(gè)問題,就是雖然循環(huán)對(duì)應(yīng)的值改變了,但內(nèi)部組件是不會(huì)重建的,即config、init不會(huì)被觸發(fā)。
理論上 by 關(guān)鍵詞之后可以接任意表達(dá)式,但是在之前版本是不生效的 (詳情看#90 regularJS的track by沒起作用) .
這個(gè)問題在最新版本已經(jīng)被修復(fù), 即你可以更精確的控制,是否要復(fù)用某一個(gè)項(xiàng)對(duì)應(yīng)結(jié)構(gòu)(內(nèi)部組件是不會(huì)重建的,即config、init不會(huì)被觸發(fā))
{#list items as item by item.id}
升級(jí)到v0.5.2減少銷毀時(shí)間
在之前的版本, Regular的模板內(nèi)容在銷毀時(shí),內(nèi)部會(huì)進(jìn)行大量的splice操作導(dǎo)致了性能問題,在0.5.2版本進(jìn)行優(yōu)化,整體銷毀時(shí)間有了 數(shù)倍的提升
總結(jié)
從操作難易度和關(guān)鍵度上,主要是以下建議
升級(jí)到Regular最新版本(也方便你使用最新的SSR、跨組件通信等特性),至少也是v0.5.2來整體提高性能(這個(gè)版本還做了不少別的性能優(yōu)化)
list記得使用by語句,特別是by item_index (item_index取決于你的命名)
組件通過isolate來控制digest深度
本文來自于那個(gè)2年只更新了0.2個(gè)版本的Regular作者之手,請(qǐng)輕噴。
下一篇應(yīng)該是關(guān)于跨組件通信的文章。
更多網(wǎng)易技術(shù)、產(chǎn)品、運(yùn)營經(jīng)驗(yàn)分享請(qǐng)?jiān)L問網(wǎng)易云社區(qū)。
文章來源: 網(wǎng)易云社區(qū)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/25332.html
摘要:以上面的例子為代表完整生命周期如下下一篇,應(yīng)該會(huì)以為例,介紹一種基于來解決跨組件的數(shù)據(jù)通信的方式免費(fèi)領(lǐng)取驗(yàn)證碼內(nèi)容安全短信發(fā)送直播點(diǎn)播體驗(yàn)包及云服務(wù)器等套餐更多網(wǎng)易技術(shù)產(chǎn)品運(yùn)營經(jīng)驗(yàn)分享請(qǐng)?jiān)L問網(wǎng)易云社區(qū)。文章來源網(wǎng)易云社區(qū) 本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。 背景在組件化不斷深入的大環(huán)境下,無論使用哪種 MDV 框架都最終會(huì)遇到一個(gè)頭疼的問題,就是「跨組件通信」。 下圖是個(gè)簡(jiǎn)單的例子 ...
摘要:最全正則表達(dá)式總結(jié)驗(yàn)證號(hào)手機(jī)號(hào)中文郵編身份證地址等是正則表達(dá)式的縮寫,作用是對(duì)字符串執(zhí)行模式匹配。學(xué)習(xí)目標(biāo)了解正則表達(dá)式語法在中使用正則表達(dá)式在中使 JS高級(jí)技巧 本篇是看的《JS高級(jí)程序設(shè)計(jì)》第23章《高級(jí)技巧》做的讀書分享。本篇按照書里的思路根據(jù)自己的理解和經(jīng)驗(yàn),進(jìn)行擴(kuò)展延伸,同時(shí)指出書里的一些問題。將會(huì)討論安全的類型檢測(cè)、惰性載入函數(shù)、凍結(jié)對(duì)象、定時(shí)器等話題。1. 安全的類型檢測(cè)...
摘要:作為開發(fā)年的開發(fā)者該如何系統(tǒng)的提升自己如今,國內(nèi)移動(dòng)互聯(lián)網(wǎng)的紅利期已過,開發(fā)工程師也從最初的一人難求,到現(xiàn)在的一個(gè)崗位百人競(jìng)爭(zhēng),僧多粥少的情況直接導(dǎo)致整個(gè)行業(yè)對(duì)求職者的要求越來越高。另外,開發(fā)越來越規(guī)范,間接導(dǎo)致項(xiàng)目對(duì)質(zhì)量要求的提升。 ...
摘要:是一個(gè)極度純凈的上傳插件,通過簡(jiǎn)單調(diào)整就可以融入到任何項(xiàng)目,支持多文件上傳上傳速率動(dòng)態(tài)控制真實(shí)進(jìn)度監(jiān)控分塊生成分塊上傳校驗(yàn)秒傳暫停取消等。 跨域?qū)W習(xí)筆記 前言: 當(dāng)一個(gè)資源,向與之所在服務(wù)器不同的域或端口請(qǐng)求另一個(gè)資源時(shí),這個(gè)HTTP請(qǐng)求,我們認(rèn)為是跨域的請(qǐng)求。出于安全考慮,瀏覽器會(huì)限制腳本發(fā)起的跨域HTTP請(qǐng)求。 那天后端讓我把token放到http請(qǐng)求頭字段里,說是為了和RN端統(tǒng)一...
摘要:順便一說,這首歌的原唱是秋田,中島當(dāng)年嗓子壞了,才有這歌。中文是直接翻譯來的,作曲是秋田。一部電影春夏秋冬又一春春夏秋冬又一春是由金基德執(zhí)導(dǎo),金英民吳英秀金基德主演的一部韓國電影。年月日于韓國上映。 原鏈接: http://bluezhan.me/weekly/#/9-2 1、web前端 Angular vs. React vs. Vue: A 2017 comparison 9 S...
閱讀 2743·2021-10-26 09:50
閱讀 2385·2021-10-11 11:08
閱讀 2128·2019-08-30 15:53
閱讀 1906·2019-08-30 15:44
閱讀 2382·2019-08-28 18:12
閱讀 2520·2019-08-26 13:59
閱讀 2853·2019-08-26 12:19
閱讀 2752·2019-08-26 12:09