距离上一篇文章过去了二十多天了,期间一直想把第二部分写完,结果在测试过程中遇到了各种坑爹的问题,到今天才算基本完成,也许还有后续,但趁着今天有时间就写出来吧,也算对这个项目的一个总结了
遇到最大问题:
项目的需求是在一个窗口里生成所有图表,还要考虑到整套打印,所以滚动加载和分页浏览不是最好的方案,这导致数据超级多的时候()
在项目结构上我们采用数据分发的方式控制组件的渲染,由大致小每层组件都对数据进行过滤,重新组成新的数据传递给下一级,根据数据去判断显示与否,由于vue里v-if的机制如果该模块数据不存在,那么组件将不被渲染
一般来说我解决问题只有两种方式,一是找到解决问题的办法,二是让这个问题彻底消失,显然第二个是在这是行不通的,所以先分析原因:
原因已经找到接下来就是解决问题
先说动画的问题,这个在echarts的api里已经提出的解决办法,有两种,我这里都用到了:
1.全部图表绘制都有动画渲染的情况
2.单个图表显示超多数据的情况
第一个可以对echarts对象设置animate属性来关闭所有动画
第二个需要设置progressive属性
progressive属性的作用如下:
该配置项就是用于配置该系列每一帧渲染的图形数,默认是 400 个,可以根据图表图形复杂度的需要适当调整这个数字使得在不影响交互流畅性的前提下达到绘制速度的最大化。比如在 lines 图或者平行坐标中线宽大于 1 的 polyline 绘制会很慢,这个数字就可以设置小一点,而线宽小于等于 1 的 polyline 绘制非常快,该配置项就可以相对调得比较大。
再说频繁操作dom导致的卡顿问题
首先感谢老大提供的的思路,这个问题可以和同步绘制一起来解决,在这里需要仔细的研究一下同步异步的问题,这个问题想清楚了,问题就解决了
JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。这个时候问题就出现了,当我在处理完数据传给图表的执行方法的时候我是这么写的:
这条被循环执行的数据多的有可能是上千条,而且这还只是其中一个模块的数据,这样的话就是上千条的数据在主线程上排队,一个图表必须要等到上一个图表绘制完毕才会绘制下一个,并且在这个时候我其他的操作都是在等待图表绘制完成的,也就是说必须要等到所有图表绘制完毕,所有页面加载出来我才能去计算页码并将其赋值,这个期间目录页的大模块页码定位全都是空白的,而这时候由于要等待所有操作完成,且cpu这时候被占满,自然而然的就造成了页面的假死状态.既然同步渲染会造成假死,那么解决方案自然就有了:异步执行绘制图表方法
先看一下异步的运行机制
数据的处理
组件的渲染(不包含图表)
页码的赋值
目录页的定位
这些主线程的任务都是可以同步进行的,且速度非常快,这样就避免了必须要等待所有图表渲染完成才能确定页码的尴尬
最开始考虑过使用定时器延时去传递数据加载图表,像下面这样
其实这样也是可行的,每一个图表的渲染都延迟执行一秒,定时器其实也算是异步执行了,当所有的主线程走完再去执行定时器的方法,但这样的话相当于有10000个定时器在等待执行啊,虽然相隔一秒,不会造成卡顿,但显然不是最优方案,
所以最终使用的是 promise的方法,这样就变成了只有一个定时器,代码如下
obj.parevArrLen</span>=<span style="color: #000000">obj.arr.length;
};
vue的munted方法代表的是所有页面加载完成再去执行,在app.vue里把promise放在这里在合适不过了,当页面渲染完成异步执行图表绘制的方法,最大程度的解决卡顿问题
ok,到这里问题解决,基本上每次滑动滚轮时图表绘制两个左右,出图速度飞快,低配置机器也可正常运行;
最后接着上一篇的打印报告来说,因为之前试验过使用HTMLtopPDF打印,所以在写项目期间就没有进行过测试,当项目完成调试打印的时候才发现由于是多页面应用所以根本无法打印,由于HTMLtopPDF是后端的解决方案,我们在前端也不好调试,所以选择了前端打印pdf的方案,
查了许多资料后决定使用 和
: 通过遍历页面DOM结构,收集所有元素信息及相应样式,渲染出canvas image
我们可以直接在浏览器端使用html2canvas,对整个或局部页面进行‘截图’。但这并不是真的截图,而是通过遍历页面DOM结构,收集所有元素信息及相应样式,渲染出canvas image。
由于html2canvas只能将它能处理的生成canvas image,因此渲染出来的结果并不是100%与原来一致。但它不需要服务器参与,整个图片都由客户端浏览器生成,使用很方便。
使用
使用的API也很简洁,下面代码可以将某个元素渲染成canvas:
通过onrendered方法,可以将生成的canvas进行回调,比如插入到页面中:
做个小例子代码如下