项目描述
长沙大屏以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. 根据项目自身选择比较好的组件库,已达到性能最优。