一個頁面中資料太多,造成頁面卡頓的優化。
當頁面渲染太多标簽時,會出現卡頓的,典型就是類似table資料太多時,非常卡頓。如果選擇分頁,沒必要讨論,這兒隻讨論采用滾動的情況。解決思路很簡單,就是頁面不展示出來的元素,從頁面上删除掉,最難點在于滾動條的處理,這兒分享一些細節思路,以上下滾動為例。
每一行固定高度,一次性擷取所有資料。
每一行不固定高度,一次性擷取所有資料。
每一行不固定高度,分批擷取資料。
首先,布局如下:

當隻顯示可視區的内容時,overflow的标簽需要删除掉,但是删除了之後,滾動條會變化,甚至消失,是以可添加padding-top和padding-bottom,以此模拟内容高度。
第一類,所有資料都能根據計算獲得,需要一個scrollTop對應的顯示資料的對照表,當滾動條位置變化時,去對照表種檢視需要顯示的資料,以此來渲染。當然不是每個scrollTop都去生成對照表,隻需要某個範圍生成就行了,比如:[{2000:顯示資料}, {5000: 顯示資料}](表示分别表示 0-2000,2000-5000顯示的資料) 去對比第一個大于scrollTop的資料,擷取其值,就是需要顯示的資料。
** 這兒需要注意的是,顯示資料必須有重複,且重複能占滿螢幕以上,避免出現空白(第一次是0-100條,第二次是80-180條)*
第二類,就不好計算了,比如某一格裡面内容太多,會令整行高度增加。可采用隐藏标簽(opacity:0),循環渲染每一行,拿到那一行的高度。此種方式簡單,也容易實作,不過計算渲染資料時,保證螢幕不出現空白的計算會複雜一點。隐藏标簽渲染時,使用分批渲染,比如每次渲染10行,使用 requestAnimationFrame,setTimeout或者promise處理一下,不至于卡死。
第三類,隻知道目前資料是多少,無法計算總高度。可以采取與第二種類似的方式,使用隐藏标簽計算出每一行的高度,最終計算出得到資料的總高度。當滾動條滾到某個值時,觸發後續資料擷取。一樣的方式,重新計算出總高度。
所有方法都有個前提,就是每一行資料渲染是同步的,有些情況是先渲染出框,等擷取資料後填充框。這種類似table的布局,會非常麻煩,需要設定一個回調函數,等所有資料渲染完成後再擷取高度。
還有一種方式,或許會更簡單,但是效果上會差一些。方法就是在滾動條距離底部某個位置的時候,觸發記錄:
記錄這一批次每一行元素的offsetTop
計算出此批次資料對照的scrollTop以及此批次資料對應的scrollHeight
記錄scrollHeight(往復原動時用)。
還需要在此時切換資料,新批次資料必須有重複資料,避免空白。這樣就可以邊滾動,邊記錄,最終記錄完成所有行資料的offsetTop,scrollTop範圍對應的批資料,以及此批的scrollHeight。父元素的paddingTop永遠是那批次資料第一行的offsetTop,而最大的scrollHeight - 目前批次資料的scrollHeight = paddingBottom。
其他優化,舉例vue,可以使用Object.freeze() 當機隻需要顯示的資料,盡量保證頁面元素少,是優化卡頓的有效方式,是以,能用v-if,盡量不要用v-show,能夠銷毀的元件,不必留着,如果為了減少請求,應當儲存資料而不是儲存标簽,keep-alive非必要不要使用。儲存标簽很容易出問題,比如使用v-if彈窗表單元件,需要手動清空資料,而直接銷毀,代碼會非常簡潔。重新渲染花費不了多少時間的。如果計算量實在太大,可以使用分批計算,異步方式處理。其作用就是在處理間隙,讓使用者的操作事件能夠響應。