項目描述
長沙大屏以vue構建的單頁面網站,每一屏以 echarts 進行繪制,圖表形式進行展示。每一屏頁面多用到定時器延時器進行頁面自動切換,圖表的圖例、指針的自動播放。
問題描述
長沙大屏在客戶現場部署,已兩小時為界點,頁面卡頓,時間越長,出現白屏頁面卡死的現狀,通過進行瀏覽器自帶的內存檢查工具檢測判斷為內存溢出導致。
期望結果
能和公司其他大屏項目一樣流暢進行展示。
版本及環境
Echarts version 【echarts版本】: 4.7.0
Browser version 【瀏覽器類型及版本】: Google Chrome
OS version 【操作系統類型及版本】: win 10 8G內存
代碼分析
1. 頁面自動切換(定時器)
分析:每次頁面切換都會用到的全局定時器,從項目啟動開始,每次的切換都會注入到內存當中,影響內存消耗
優化:只在當前標簽頁面被激活的時候開啟,其他情況下及時清除定時器。
1 let index = 0; 2 let isEnter = false; 3 let clearTime = null; 4 let ifCycle = true; //默認輪播 5 document.addEventListener("visibilitychange", () => { 6 if (document.hidden) { 7 // 清除定時任務 8 clearInterval(clearTime); 9 } else { 10 // 開啟定時任務 11 if(ifCycle){ 12 clearTime = setInterval(() => { 13 isEnter = true; 14 if(index >= routerName.length) index = 0; 15 window.location.href = '/#/' + routerName[index]; 16 index++; 17 }, 20000); 18 } 19 } 20 }); 21 router.beforeEach((to, from, next) => { 22 //鍵盤事件控制輪播 23 document.ondblclick=function(event){ 24 ifCycle = ifCycle===true?false:true; 25 // let message=ifCycle===true?'輪播':'頁面已進入演示模式'; 26 // let showClose = ifCycle===true?false:true; 27 // let duration = ifCycle===true?3000:0; 28 // ElementUI.Message({message,type: 'success',duration:duration,showClose: showClose,}); 29 console.log(ifCycle===true?'輪播':'頁面已進入演示模式'); 30 clearInterval(clearTime); 31 if(ifCycle){ 32 clearTime = setInterval(() => { 33 isEnter = true; 34 if(index >= routerName.length) index = 0; 35 next('/' + routerName[index]) 36 index++; 37 }, 20000); 38 } 39 } 40 clearInterval(clearTime); 41 if(PROJECT === 'changsha') { 42 if(to.path === '/login') { 43 return next(); 44 } 45 console.log(index); 46 if(ifCycle){ 47 clearTime = setInterval(() => { 48 isEnter = true; 49 if(index >= routerName.length) index = 0; 50 next('/' + routerName[index]) 51 index++; 52 }, 20000); 53 } 54 } 55 next(); 56 })
2. 每屏頁面內部(定時器)
分析:每屏頁面圖表的指針、提示框展示自動播放定時器在20s,在頁面朓轉之后定時器依然存在,影響內存消耗。
優化:在每次頁面朓轉之后的進行判斷清除定時器,以確保每次進入頁面的定時器重新開始,不會保留多於的定時器。
beforeDestroy() { clearInterval(showTip); showTip = null; }
3. echarts組件(實例影響)
分析:每屏頁面的圖表多用於echarts對象實例生成,圖表過多的話,實例對象就有很多,極大影響內存消耗。
優化:每次朓轉頁面之后的進行判斷,及時清除實例,以確保每次進入頁面時實例化圖標都是最新的,沒有過多的多於實例化對象。
beforeDestroy() { echarts.dispose(myChart); clearInterval(showTip); showTip = null; }
4. echarts、定時器(初始變量)
分析:echarts 初始化變量不可在data 中定義初始變量,vue會把此變量賦值內存增大。定時器(初始化變量)也保持一致
優化:不在data中定義,在組件內部初始定義空值(null)
let myChart = null, showTip = null;
5. ecahrts(版本)
分析:之前版本的echarts 版本為4.21,版本內部穩定優化需要選擇符合對應項目的版本。
優化:版本由之前的4.21升至4.7.0,對於一些可以用到svg 渲染的已更換至svg
官方:Apache EChartsTM 從初始一直使用 Canvas 繪制圖表(除了對 IE8- 使用 VML)。而 ECharts v4.0 發布了 SVG 渲染器,從而提供了一種新的選擇。只須在初始化一個圖表實例時,設置 renderer 參數 為 'canvas' 或 'svg' 即可指定渲染器,比較方便。
上圖顯示出,在這些場景中,SVG 渲染器相比 Canvas 渲染器在移動端的總體表現更好。當然,這個實驗並非是全面的評測,在另一些數據量較大或者有圖表交互動畫的場景中,目前的 SVG 渲染器的性能還比不過 Canvas 渲染器。但是同時有這兩個選項,為開發者們根據自己的情況優化性能提供了更廣闊的空間。
myChart = echarts.init(document.getElementById('two'), null, {renderer: 'svg'});
總結
1. 對於echarts 圖表過多類似的項目,實時請求接口、組件內部的渲染、實例對象的構成對內存消耗很大,需要對其進行內存消耗的及時處理。
2. 根據項目自身選擇比較好的組件庫,已達到性能最優。
