摘要:懶加載方式常見的有淘寶一屏用元素占據(jù)一定的高度,然后再去拉圖片數(shù)據(jù)。但這種方式還是需要元素占位,淘寶一頁的數(shù)據(jù)量其實不算大,因為它結(jié)合了分頁。
背景
大數(shù)據(jù)項目根據(jù)用戶輸入代碼查詢數(shù)據(jù),用戶的代碼不可控(比如select from db limit 5000),有可能一頁需求要求展示100行5000列數(shù)據(jù)。由于是用戶代碼實時查詢的數(shù)據(jù),后端不可能將所有查詢結(jié)果都存儲。因此,查詢的結(jié)果是實時的、全量的,分頁和排序都需要前端去實現(xiàn)。
剛開始的接手項目的時候完全不能展示十萬級的數(shù)量,chrome標(biāo)簽頁直接崩潰。這個在分析了需求,展示數(shù)據(jù)不需要響應(yīng)式后,用了Object.freeze()后就可以勉強(qiáng)展示十萬級數(shù)據(jù)。雖然還是卡頓,但是需求已經(jīng)實現(xiàn)。(值得注意的是Object.freeze()并不是深度凍結(jié),實際應(yīng)用中對象要進(jìn)行遞歸操作。)
下面圖展示的是100行乘以一千列,在左右拖拽0-150列。目前也對超過兩百列的數(shù)據(jù)進(jìn)行橫向的懶加載操作,實現(xiàn)原理時監(jiān)聽scroll事件滾動到末尾時截取對應(yīng)下一組數(shù)據(jù),然后將滾動條恢復(fù)到頭部??梢詮膅if中明顯感覺到這個過程是滾動條恢復(fù)到原狀之間耗時比較長。而且當(dāng)用戶想要看前一組數(shù)據(jù)的最后一項和后一組數(shù)據(jù)的前一項時,js就要不停地做截取數(shù)據(jù)的操作重新渲染,開銷非常大。
利用chrome devtool performance進(jìn)行性能分析。(進(jìn)行性能分析時使用隱身模式避免chrome插件對結(jié)果分析造成偏差)
觀察FPS圖表,有幾段紅幀證明這過程中頁面超負(fù)荷,會出現(xiàn)卡頓響應(yīng)緩慢等。
選中紅幀區(qū)域,Main區(qū)域發(fā)生變化,變?yōu)楫?dāng)前選擇時段的函數(shù)調(diào)用棧詳情。點擊會在下面的Summary里發(fā)現(xiàn)對應(yīng)的信息以及警告提示回流可能為性能的瓶頸Forced reflow is a likely performance bottleneck.。對應(yīng)的問題出在監(jiān)聽scroll事件后出現(xiàn)的js代碼中,執(zhí)行的次數(shù)非常多。不僅需要去讀取scrollLeft值,還因為重新渲染數(shù)據(jù)時使組件縱向高度發(fā)生了改變,進(jìn)而多次觸發(fā)了element-ui組件的updateScrollY方法。從Screenshots可以看到這時剛好是數(shù)據(jù)移動到最后要對數(shù)據(jù)進(jìn)行截取重新渲染。
從上圖summary可以看到j(luò)s的運行壓力很大,勾選memory項紀(jì)錄js heap占用情況,查看到占用高達(dá)161mb-325mb
table的數(shù)據(jù)并不會有修改的需要,僅僅是展示,并不需要響應(yīng)式。Object.freeze()可以阻止vue追蹤屬性的變化,減少性能的開銷
由于數(shù)據(jù)展示的table不僅大量而且經(jīng)常變換數(shù)據(jù)集。為了減少回流和重繪,table做絕對定位脫離文檔流,避免布局抖動。
由于后端返回的數(shù)據(jù)一組表頭和內(nèi)容分開的數(shù)組,而開源element-ui的vue組件都是以key:value的形式,大量數(shù)據(jù)情況下僅僅是將數(shù)組轉(zhuǎn)化為key:value的形式就花費掉幾百毫秒的時間。開源組件能解決的是通用情況,這種情況下為了盡量減少開銷重寫適用于業(yè)務(wù)的table組件還是很有必要的。
//后端返回的格式 data = [ columnName: ["col1", "col2", ……], columns: [ ["1", "2", ……], ["1", "2", ……], …… ] ] // 開源組件需要的格式 data = [ { col1: "1", col2: "2", …… }, { col1: "1", col2: "2", …… } ]
后端返回的數(shù)據(jù)量有可能高達(dá)百萬級,盡管前端進(jìn)行分頁還是有可能要展示到數(shù)量達(dá)十萬。其中行最多每頁只展示100條,但是列由ide用戶執(zhí)行的代碼決定,這里主要影響性能的是列數(shù)。列數(shù)有可能為1000條,模擬橫向懶加載,將拿回來的數(shù)組截取部分展示,減少頁面上的dom節(jié)點。但是目前模擬懶加載的方式用戶體驗不好。
為了解決橫向滾動時相鄰列的數(shù)據(jù)能夠展示在同一屏上,而不需多次來回切換,首先做的工作是在截取數(shù)據(jù)時保留前一屏的數(shù)據(jù),拖動后滾動條回到中間位置,在一定范圍內(nèi)不需要多次滾動才能查看。(如下圖)
- 但這種方式也是非常不友好,每次滾動到最后要去檢測用戶是否按著鼠標(biāo)有沒有抬起,防止觸發(fā)多次數(shù)據(jù)重新渲染。因為這種情況下,用戶拖一次只能加載一組新數(shù)據(jù),滾動條便回到了中間位置,如果用戶需要看到最后一組數(shù)據(jù)就要多次操作。正常的懶加載應(yīng)該是有一條適應(yīng)高度的滾動條拖拽,無縫連接。 - 懶加載方式常見的有: 1. 淘寶一屏用元素占據(jù)一定的高度,然后再去拉圖片數(shù)據(jù)。滾動條便適應(yīng)高度的拖動距離。但這種方式還是需要元素占位,淘寶一頁的數(shù)據(jù)量其實不算大,因為它結(jié)合了分頁。 2. 掘金沸點的無限加載:掘金的方式是監(jiān)聽到底部時,再去拉響應(yīng)的數(shù)據(jù)追加,滾動條會自適應(yīng)滾到相對應(yīng)的地方。但是掘金這種懶加載一直加載數(shù)據(jù)沒有截取掉舊數(shù)據(jù),所以滾動條距離也是一直適應(yīng)數(shù)據(jù)的。嘗試將掘金沸點一直拖動到2000條,網(wǎng)頁已經(jīng)開始有點卡頓。而在ide項目中,兩千條數(shù)據(jù)算是少量數(shù)據(jù)。 - 啟發(fā)于[https://github.com/tangbc/vue-virtual-scroll-list](vue-virtual-scroll-list),利用了padding值模擬了淘寶固定高度,不需要元素占位,模擬出全部數(shù)據(jù)量的滾動條縱向滾動距離,拖動時完全無感知數(shù)據(jù)的重新渲染。目前vue-virtual-scroll-list只支持縱向,但稍微改造下就能用在ide項目的橫向懶加載。(改造后如下圖,gif軟件錄制時稍微有點卡頓感)
scroll長時間運行的重新計算樣式事件,其時間如果超過 16.7 毫秒,并且恰好發(fā)生在滾動期間,導(dǎo)致用戶體驗到明顯的抖動。為了在拖動過程中數(shù)據(jù)變化以連貫、平滑進(jìn)行過渡,函數(shù)節(jié)流改setTimeout為requestAnimationFrame(rAF),由系統(tǒng)來決定回調(diào)函數(shù)的執(zhí)行時機(jī);它能保證回調(diào)函數(shù)在屏幕每一次的繪制間隔中只被執(zhí)行一次,這樣就不會引起丟幀現(xiàn)象,也不會導(dǎo)致渲染數(shù)據(jù)出現(xiàn)卡頓的問題,并且rAF能兼容到ie9以上了。
優(yōu)化后結(jié)果分析拖動幾百條數(shù)據(jù)截取的performance在FPS圖表中已經(jīng)沒有最初的紅標(biāo),沒有Forced reflow,每幀的rendering也由rAF控制在16.7ms以內(nèi),js內(nèi)存占用也從161mb-325mb,降低到157mb-196mb。
組件接口設(shè)計原則復(fù)用性:配置參數(shù)的方式去差異化體現(xiàn),參數(shù)的可配置性提高了組件的復(fù)用率和靈活性。
可維護(hù)性:組件化后,組件內(nèi)部的邏輯只對組件負(fù)責(zé),外部的邏輯只通過配置參數(shù)適配,提高了代碼的邏輯清晰度,可以快速定位代碼出現(xiàn)問題的地方。
這個組件設(shè)計時對外提供toLeft,toRight,onScroll事件,分別是滑動過程中到了頭、尾,及滑動過程的回調(diào)。提供了offset,remain,bench參數(shù)表示剛渲染時的偏差,顯示的列數(shù),及保留多少列在實際dom中。
小結(jié)以前沒有想過js也會承受那么大的壓力,一點點優(yōu)化都能顯著減輕內(nèi)存。在寫代碼時要特別關(guān)注高頻事件的觸發(fā),一切的優(yōu)化方向就是在實現(xiàn)功能的前提下減少重新渲染的發(fā)生。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/98196.html
摘要:無論是開發(fā)新手還是經(jīng)驗豐富的老手,我們都喜歡開源軟件包。所幸的是,隨著社區(qū)的不斷壯大,每天都會出現(xiàn)一些很好的軟件包。在下文中,我們將推薦一些非常好用的開源庫是一個非常易用的漸進(jìn)式框架,用于構(gòu)建用戶界面。的一個極簡主義的深色設(shè)計系統(tǒng)。 無論是開發(fā)新手還是經(jīng)驗豐富的老手,我們都喜歡開源軟件包。對于開發(fā)者來說,如果沒有這些開源軟件包,很難想象我們的生活會變得多么疲憊不堪,而且靠咖啡度日也會成...
摘要:在做業(yè)務(wù)組件的時候需要自己自己封裝一個通用的表格,這個表格需要符合我們一切的好的幻想,左右固定,表頭固定,分頁,選擇,一直表格內(nèi)容的行數(shù)限制等等,下面就為大家介紹一下這一款表格組件功能以及怎么使用。 在做業(yè)務(wù)組件的時候需要自己自己封裝一個通用的表格,這個表格需要符合我們一切的好的幻想,左右固定,表頭固定,分頁,選擇,一直表格內(nèi)容的行數(shù)限制等等,下面就為大家介紹一下這一款表格組件功能以及...
摘要:正例復(fù)制代碼反例復(fù)制代碼組件數(shù)據(jù)組件的必須是一個函數(shù)。正例更好的做法復(fù)制代碼反例這樣做只有開發(fā)原型系統(tǒng)時可以接受復(fù)制代碼為設(shè)置鍵值總是用配合。這條規(guī)則只和單文件組件有關(guān)。基于Vue官方風(fēng)格指南整理一、強(qiáng)制1. 組件名為多個單詞組件名應(yīng)該始終是多個單詞的,根組件 App 除外。正例:exportdefault{name:TodoItem,//...}復(fù)制代碼反例:exportdefault{n...
摘要:在此,我們可以使用懶加載方式對其進(jìn)行優(yōu)化,僅展示其對應(yīng)類型的圖,避免了不必要的資源浪費和計算時間。 這篇文章將介紹下實際使用performance對頁面進(jìn)行優(yōu)化的過程。總的來說,chrome performance工具讓我們更方便的發(fā)現(xiàn)在代碼運行過程中的問題在哪里,便于對一些可能注意不到的問題進(jìn)行定位、分析和優(yōu)化。原文首發(fā)于個人博客 渲染優(yōu)化 首先,我們對進(jìn)入整個詳情頁進(jìn)行分析,整個頁...
閱讀 967·2021-10-13 09:39
閱讀 3637·2021-09-26 10:16
閱讀 2963·2019-08-30 15:54
閱讀 1114·2019-08-30 14:22
閱讀 2949·2019-08-29 15:39
閱讀 3354·2019-08-27 10:52
閱讀 863·2019-08-26 13:59
閱讀 1835·2019-08-26 12:20