项目背景
客户自服务项目是为专网客户进行网络服务管理的Saas应用,旨在为客户提供便捷快速的网络服务支撑与展示,其中的可视化大屏作为客户端数据直观呈现的重要入口,产品侧希望给予用户侧一定的私人自定义功能,因而本文简单介绍了下相关实现的一些思路以及代码实现过程中一些比较有意义的bug回顾分析
项目方案
拿到产品需求的第一反应是low/no code实现方案,但业界较为常见的是H5页面的定制(ps:开源的大屏low code方案可以看一下小夕大佬的从零开发可视化大屏制作平台),并且其数据量不具有特殊性,基于产品的需求,这里只借鉴了其schema统一设定的方案(ps:这个很重要,大部分low code的自定义schema其实最后是前后端同构的,这样可以无缝处理,但要考虑到各个技术团队的不同技术侧重,这种约定需要比较好的处理),对于其他的拖拽及网格编辑器等的方案会根据后续产品相关迭代进行逐步扩展
通用schema方案
业界常见的schema方案是将用户配置与自身配置进行分离,也就是对是否暴露给用户进行区分,这里选择将暴露给用户的schema定义为:
{
requestParams: {
},
figureParams: [
]
}
这里的requresParams主要是向后端发送请求拿到对应数据的内容,而figureParams则是用户自定义的一些配置信息,其中包含了图形化的一些展示信息
响应式函数编程
可视化大屏往往和大数据分析与统计相关联,对于数据流的处理,使用函数式编程将数据处理进行转换,可以更好的进行响应式编程方案,这里参考了一些响应式RxJS的设计思想及函数式编程的链式处理、effect、pure Function等理念,对于后续大数据的处理也可以更好的和Flink等相结合,对于想了解RxJS与Flink相关扩展的同学可以参考阿里同学的这篇文章从 RxJS 到 Flink:如何处理数据流?
export const handleKpiGroupId = function(staticTypes) {
const arr = staticTypes.map(staticType => staticType.split('-')[0]);
return Array.from(new Set(arr));
}
export const handleKpiNameEns = function(staticTypes) {
const arr = staticTypes.map(staticType => staticType.split('-')[1]);
return Array.from(new Set(arr));
}
根据业务需要封装一些map及filter处理,后续会依据数据流进行相关的发布订阅的响应式处理
踩坑案例
从数组中删除位置数组中的元素
[bug描述] 在客户指标图表穿梭框组件中对已选择图形进行取消选择操作,这里是通过一个checked拿到对应左侧push的栈结构数据的位置,在删除过程中使用了“占位符”进行splice替换,导致图形配置信息遗漏到大屏展示页面
[bug分析] 使用splice操作进行占位后再进行占位符过滤操作,用户快速点击提交导致子组件向父组件emit数据未能同步到变已作出提交,导致脏数据遗漏到大屏展示页面
[解决方案] 直接使用filter操作进行处理,避免splice的操作污染,需要注意filter会返回新数组,对原数组不做处理,因而vue监听时需要对数组进行重新的地址修改
复杂数据类型地址引用问题
[bug描述] 穿梭组件中对于向父组件派发的数据通过一个stack栈存储,而该栈中存储了echarts的options等复杂数据类型,结果导致了数据共享问题
[bug分析] js中负载数据类型,如:对象、数组是存放在堆内存中的,在栈内存中存储的仅仅是一个地址引用
[解决方案] 使用深克隆进行数据备份,从而实现数据的隔离
父组件异步数据通过props传递问题
[bug描述] 父组件异步请求获取数据后传递给子组件时,子组件拿到的数据无法立即在页面上实时渲染
[bug分析] 这里出现了两次,一次是父组件给子组件传递数据没有立即监听到,而页面需要立即渲染导致的bug,此时对传递的props进行了监听处理;另一次是父组件中和子组件中都调用了一个接口,只是需求不同,我希望能够减少请求次数,结果导致了父组件传递的数据并未同步传递给子组件,props会受到上一次值的影响
[解决方案] vue的数据监听并非同步渲染到dom上,这里会出现一个tick的延时,如果需要父组件中数据实时传递给子组件可以考虑在子组件中监听,以及使用$nextTick等
Object.keys返回数据排序问题
[bug描述] 大屏展示横坐标是时间维度,这里会从服务端拿到时间粒度的数据,而存储的key值为时间,因而需要对数据进行过滤整合处理,使用Object.keys对时间粒度返回的过程中出现了时间粒度的乱序
[bug分析] js中的Object.keys会对不同情况进行不同的策略排序,更深层次的探索可以看腾讯IMWeb同学分享的关于Object.keys排序的深层探究关于 JavaScript Object.keys() 排序问题的探索
[解决方案] 使用sort对排序规则进行确定
总结
大屏可视化定制看似简单,但在实际开发过程中还是会出现很多的问题,尤其是涉及到了数据的分析与处理,整个定制的核心在于schema的确定,需求的不同也会导致schema的变动,因而对于大数据相关的开发与展示可能会是可视化方向的另一个扩展方面,这里可以着重看一下响应式函数编程与大数据相关的结合,可能能碰撞出一些火花;另外就是对于bug进行不同层次的深度剖析,在每次开发功能过程中产生的bug,总有那么几个值得回味反补的闪光点存在,就像“错题本”一样,总会出现那么一两个值得我们反复玩味的bug,从而让我们对基本原理能有一个更深层次的理解,人都对不常见的问题印象深刻,真正踩过几次坑,才能印象深刻,所谓“痛则通,不痛则不通”,每一次的bug流的泪都是当初脑子进的水,希望大家能在不断实践的过程中反补自己技术基础的不足,从而把自己的技术打造的更为精湛与过硬,高手过招总在细节中体现功夫的深浅,共勉!!!