原創(chuàng)聲明
本文系作者辛苦碼字所得,歡迎分享和轉(zhuǎn)載,但請在明顯位置注明作者的如下信息:
筆名:來碗雞蛋面
簡書主頁:http://www.reibang.com/u/4876275b5a73
郵箱:job_tom@foxmail.com
CSDN ID:tom_wong666
背景:Vue+Echarts+mintUI開發(fā)移動端app
問題:Echarts圖表在IOS端懶加載多個時出現(xiàn)閃退
問題分析:
頻繁操作App直到閃退出現(xiàn)仍稀,監(jiān)控內(nèi)存使用情況后發(fā)現(xiàn)地消,在操作過程中內(nèi)存一直升高废赞,到600M時軟件閃退虎眨;
考慮從兩方面解決:
一,減輕echarts圖表渲染的壓力(只渲染視口內(nèi)的圖表)祷安;
二姥芥,抑制頻繁請求,減輕內(nèi)存壓力(抑制無效請求)汇鞭;
一凉唐,減輕echarts圖表渲染的壓力:
處理步驟1:
因為同一個組件做了復(fù)用庸追,通過點擊事件改變params來區(qū)分A組圖表和B組圖表。一開始推測是切換AB組時數(shù)據(jù)未清空導(dǎo)致的熊榛,所以點擊事件時給數(shù)據(jù)做了重置清空動作(this.list=[];)锚国。這樣處理之后,進行測試玄坦,結(jié)果發(fā)現(xiàn)內(nèi)存在起伏中上漲血筑,最終還是會達到600M而崩潰;
處理步驟2:
到這里考慮是否在某個時機(改變AB組圖表時或者什么時候)銷毀組件煎楣,但是vue的.$destory只能銷毀一個實例:清理它與其他實例的鏈接豺总,解綁它的全部指定以及事件監(jiān)聽,并不會銷毀/影響DOM展現(xiàn)择懂。DOM展現(xiàn)還在喻喳,就表示前面展現(xiàn)過的圖表都還在內(nèi)存中占用空間。
所以辦法就是用v-if強制移除DOM困曙。想到就去嘗試表伦,思路是:
給eCharts組件加v-if=“isShow”,isShow通過touch事件觸發(fā)scrollTop的值變更來決定是否顯示;步驟三展開講具體實現(xiàn)慷丽。
處理步驟3:
先說明一下變量/常量
(1)mainPage元素蹦哼,echarts畫布元素的頂級父元素;
(2)6rem,chart元素/畫布的固定高度要糊;
算法是:
touchend(){
//touchend時獲取畫面滾動距離的rem值
let scrollRem=mainPage.scrollTop/document.documentElement.fontSize;
//獲取頁面滾動和echarts元素高度的比例值
this.scrollStep=scrollRem/6;
}
//對于每一個echarts元素是否視口內(nèi)的判斷
<chart v-for="(item,index of data)" :key="index"
v-if="index > scrollStep-1 && index<scrollStep+1">
</chart>
處理步驟4:
考慮到業(yè)務(wù)需求纲熏,懶加載的目的是可以順暢瀏覽,所以一般都會在視口之外預(yù)先渲染幾個圖表锄俄。實現(xiàn)這個局劲,只要改變判斷條件就好了,這里以預(yù)加載三個圖表為例:
//一次渲染三個圖標(biāo)為例
<chart v-for="(item,index of data)" :key="index"
v-if="index > scrollStep-1 && index<scrollStep+3">
</chart>
處理步驟5:
步驟4處理后奶赠,實際驗證時發(fā)現(xiàn)鱼填,正常滑動瀏覽器/手機端app頁面沒問題车柠,但是快速滑動時剔氏,頁面慣性導(dǎo)致在手指離開屏幕后繼續(xù)移動了兩屏,此時出現(xiàn)bug:有圖表進入視口竹祷,但是沒有渲染;
分析后發(fā)現(xiàn)羊苟,問題在于觸發(fā)scrollStep的時機不對塑陵,目前是在touchend時觸發(fā)一次,導(dǎo)致在上面的情況下無法控制進入視口的圖表渲染蜡励。
解決方法:把scrollStep放入onscroll事件中計算令花,在頁面滾動時實時觸發(fā)阻桅。
依據(jù)我們的渲染條件,只有scrollStep變更達到6rem才觸發(fā)一次圖表渲染變更兼都,其他時候只在onscroll事件中只觸發(fā)了兩行獲取和計算的代碼嫂沉,資源消耗壓力不大。
onscroll(){
//獲取畫面滾動距離的rem值
let scrollRem=mainPage.scrollTop/document.documentElement.fontSize;
//獲取頁面滾動和echarts元素高度的比例值
this.scrollStep=scrollRem/6;
}
二扮碧,抑制頻繁請求趟章,減輕內(nèi)存壓力:
處理步驟6:
經(jīng)過以上五步之后,內(nèi)存得到了一定程度的釋放慎王,但在如下極限條件下仍然會出現(xiàn)內(nèi)存飆升閃退情況:
如上圖蚓土,AD是App的導(dǎo)航,所有的導(dǎo)航指向同一個組件E赖淤,持續(xù)快速切換ABCD蜀漆,約兩分鐘后內(nèi)存飆升超過600M,軟件再次閃退咱旱。AD組件每次點擊需要給E組件發(fā)起6個請求确丢,重復(fù)多次點擊時累計了大量的頻繁請求掛起和持續(xù)返回,造成了內(nèi)存的大量累計吐限。
對策:給頁面加上“數(shù)據(jù)加載中”模態(tài)框鲜侥,在數(shù)據(jù)請求回來之前禁止頁面操作,避免頻繁的無效操作增加內(nèi)存壓力毯盈。
說明:匆忙之中來不及做具體的演示demo剃毒,只理了一下思路,若遇到類似問題搂赋,參考思路就好赘阀。