BI 数据可视化平台建设(2)—筛选器组件升级实践
作者:vivo 互联网大数据团队-Wang Lei
本文是vivo互联网大数据团队《BI数据可视化平台建设》系列文章第2篇 -筛选器组件。
本文主要介绍了BI数据可视化平台建设中比较核心的筛选器组件, 涉及组件分类、组件库开发等升级实践经验,通过分享一些对交互和业务耦合度高的组件开发迭代的思考,希望可以给正在做组件重构解耦的读者带来启发。
往期系列文章:BI 数据可视化平台建设(1)—交叉表组件演变实战
一、引言
BI产品通常包含大量复杂的数据信息,需要对其进行快速和准确的处理和分析。筛选器可以帮助BI产品的用户快速地定位所需信息,并从海量数据中筛选出有用的数据,以便进行深入的分析和决策。敏捷BI作为公司内部用户数最多的可视化平台,随着平台的业务增长和版本迭代,其筛选器功能也越来越丰富和完善,旧的设计架构也显得越来越臃肿且难以维护,为了提高筛选器使用的稳定性和降低后续迭代维护成本,筛选器的架构升级已经不可避免了,本文主要给大家介绍一下筛选器组件的架构升级实践经验。
二、前期设计
2.1 组件选型
前期筛选器组件的职责和交互比较简单,主要是对图表数据进行单向的数据过滤,并没有应用到其他的业务场景中,所以前期的组件设计主要以 业务组件 的思路进行开发实现。
2.2 组件分类
组件类型主要可以分为业务组件和通用组件两种,它们在组件的状态管理和界面渲染的设计和实现上是完全不同的。
但无论是业务组件或者通用组件都具备组件本质所包含的三个性质 扩展、通用、健壮:
- 扩展性:在原有组件基础上可 二次封装 扩展成新的组件符合设计的开闭原则。
-
通用性:根据组件接受的参数和组件中与业务的解耦比来衡量组件的通用性,并不是通用性占比100%的组件就是最好的组件,需要根据 不同的场景 分析。
-
健壮性:避免组件中参数处理和函数执行过程可能出现的奔溃和错误导致程序的直接挂断,单测以对组件内部 做好边界处理,异常错误的捕获来衡量这一标准。
因此两种组件类型没有绝对优劣之分,重要的是在保证组件设计的基本原则不变的情况下,根据不同的业务场景和需求选择合适的类型 。无论哪种组件,随着不断扩展,使其通用性提升,必然就会降低组件的易用性质;而不断丰富一个组件,也会导致其组件代码过长、组件使命不单一、不易读、不易维护;因此组件设计除了要保证组件的基本性质,还要通过明确组件职责、组件拆分粒度以及良好的代码结构和Api设计规范对组件的迭代进行约束,避免代码逻辑的过度叠加和膨胀。
2.3 背景痛点
旧版筛选器组件设计存在维护成本高且问题BUG多等问题,主要由两个原因造成,第一个是业务发展,随着业务的快速增长,筛选器组件的功能也越来越丰富和完善,由原来的单一功能升级成可以支持数据预警、个性化分析等多种业务场景的核心模块;第二个是缺乏规范约束,主要是缺少良好的代码结构和清晰的组件职责等规范约束,导致业务逻辑过度叠加,粒度拆分不合理,文件多,且文件名不规范。最终导致了筛选器组件的稳定性越发不可控。
由于前期设计不合理和缺乏规范约束,筛选器组件经过了一段时间的野蛮式迭代扩展带来了以下的痛点问题:
-
重复代码多,复用性差:相同的业务逻辑需要维护多份代码,导致出现bug的概率大大增加,后期维护成本增加;
-
业务耦合度高,缺乏设计模式进行管理:更新迭代过程中处理逻辑需要兼容多种场景代码越来越复杂,导致问题难以跟踪,难以定位问题意味着你可能需要花大部分的时间处理问题;
-
编码风格不一致,维护成本高: 项目主要技术栈是Vue,但是代码风格有大部分格使用的React的jsx形式进行开发;项目存在多人维护,个人技术参差不齐;导致后续学习成本增加;
-
组件嵌套层级深,存在双向数据流:不符合Vue 单向数据流状态管理理念,无法追踪局部状态的变化,增加了出错时 debug 的难度,经常出现修改一个模块bug而引起其他模块bug的情况。
三、新版架构设计
3.1 设计思路
旧版的组件随着业务发展迭代,已经混杂着大量的业务逻辑,组件耦合严重,职责也越发不清晰,因此为了合理的划分组件职责和清晰代码结构,新的架构设计将基于 通用组件 的设计思路,将筛选器组件抽离出BI业务;从BI项目的架构、技术选型、文档使用等多个方面进行考虑,在原来的基础上改造太复杂,可行性低,所以搭建了一个新的项目,将之前所有的筛选器组件迁移到新项目上,稳定后替换BI项目上所有旧版筛选器组件,后续统一只需维护一个组件库(bi-filters)。
3.2 实现方案
筛选器组件库(bi-filters)主要 基于Vue CLI 的 开发/构建目标/库 能力以及 Lerna 包管理工具 进行设计开发,这种组件库设计集成了以下特点:
-
按需引入:每个UI组件都是一个npm包,多语言、工具和样式都是自成体系的npm包,可被业务或UI组件灵活引用,同时天然支持按需加载。
-
配置简单:如果需要进行构建处理,那么每个npm包可单独进行构建配置,配置变得更加简单。结合Vue CLI的构件库能力,对于简单UI组件的构建几乎可以做到webpack零配置。
-
独立部署:组件库的版本迭代可以更快,不需要进行整体构建,每个组件可单独快速发布。
1. 利用 Lerna工具进行多包管理,快速对组件库进行版本发布
组件库目录结构:
2. 组件设计和实现
参考 装饰器设计模式,对组件进行抽象设计,从而达到业务状态与 UI 状态隔离,UI 状态与交互呈现隔离的目的。具体实现是先按功能将组件拆成展示层,逻辑层,容器层,达到组件分层可复用。再通过
$attrs/$listeners对antd组件进行二次封装,抽离成在筛选器组件库内的公共组件,达到交互可组合。最终使得组件边界清晰,符合设计规范中提到的开闭原则、单一职责原则、里氏替换原则。
以文本下拉筛选器组件(TextDropDownFilter)实现为例:
(1)按功能将组件拆分成 容器层、逻辑层(搜索框逻辑层、 下拉列表逻辑层 )、展示层(搜索框展示层、下拉列表展示层):
(2)BI项目中使用 :引入筛选器组件后, 在BI应用层处理业务场景,将处理业务后的状态信息通过 Vue 插槽(Slots)的方式传递给底层的筛选器组件 。
<!-- page.vue一 -->
<TextDropDownFilter><template #addonSearchAfter><!-- 业务场景一 --> <a-tooltip v-if="xxx"><BIIcon type="icon-jilian" class="btn-jilian" v-show="xxx"></BIIcon></a-tooltip><!-- 业务场景二 --> <a-tooltip v-if="xxx"><AIcon type="warning" theme="filled" class="btn-warning"></AIcon></a-tooltip></template>
</TextDropDownFilter>
(3)搜索框逻辑层:接收业务处理后的状态,进行不同的UI组合展示
<!-- SearchHandler.vue一 -->
<template><div class="bd-search" :class="{ 'active': inputActive }"><!-- 基础搜索框组件 一 --> <Searchv-bind="$attrs":searchValue="searchValue":placeholder="placeholder"@searchItem="handleSearchItem"@pressEnter="handlePressEnter"@focus="handleFocus"@blur="handleBlur"></Search><!-- 业务层传入的UI 一 --> <slot name="addonSearchAfter"></slot></div>
</template>
(4)搜索框展示层:由 antd 基础组件组成,提供交互单一且可复用的UI组件
<!-- Search.vue一 -->
<template><AInputclass="common-search-input":placeholder="placeholder":value="searchValue"allow-clear@change="change"v-on="$listeners"@pressEnter="$emit('pressEnter', $event)"><AIcon slot="prefix" type="search" /></AInput>
</template>
3. 最后利用 Vue CLI 的构建库功能,对不同类型的筛选器组件进行单独构建打包
vue cli 的构建库能力可以通过 --target 选项指定不同的构建目标。它允许你将相同的源代码根据不同的用例生成不同的构建。
在组件库项目的 packages 目录下,每一个筛选器组件的目录下都需要创建 package.json文件,用于组件的构建信息配置:
{"name": "@bigdata/TextDropDownFilter", //包名"version": "0.0.0", // 版本号"private": false, // 为true时不会被发布"main": "dist/编译文件名.umd.min.js","scripts": {"build": "vue-cli-service build --target lib --name 编译文件名 --dest dist ./index.js","lint": "","test:unit": ""},"files": ["dist"],"author": "","license": "ISC","description": ""
}
四、效果收益
1. BI项目整体代码量减少,组件目录结构清晰,只需要专注维护业务逻辑
2. BI业务抽离后,筛选器组件可进行独立维护迭代,减少代码耦合,只需专注功能交互和性能优化,提高组件稳定性。
五、总结
从上述的升级过程可以看出,组件的抽象与抽象粒度是没有一成不变的统一标准,也没有对与错。组件的设计更多的应该去关注如何适配不同的业务场景和需求要求,追求更多的是“适合”。有的时候,同样的业务场景,组件粒度的标准也会随业务场景变化而变化,甚至可能随场景增加而持续重构,因此为了代码更好的维护和分层,以及避免代码逻辑的过度叠加和膨胀,必须制定一些组件抽象的规范加以约束。总的来说,组件开发的方法论可能是相对中立和普适的,但组件库的整体建设方案,与所在的行业和业务有很大的关系。不同的行业领域,对交互展现的掌控程度是不一样的,因此设计组件库方案的时候,应该优先从产品项目的集成关系角度出发看待问题,这样可以保证业务的拓展和可用性尽可能不被技术方案限制。
相关文章:

BI 数据可视化平台建设(2)—筛选器组件升级实践
作者:vivo 互联网大数据团队-Wang Lei 本文是vivo互联网大数据团队《BI数据可视化平台建设》系列文章第2篇 -筛选器组件。 本文主要介绍了BI数据可视化平台建设中比较核心的筛选器组件, 涉及组件分类、组件库开发等升级实践经验,通过分享一些…...

RabbitMQ 安装及配置
前言 当你准备构建一个分布式系统、微服务架构或者需要处理大量异步消息的应用程序时,消息队列就成为了一个不可或缺的组件。而RabbitMQ作为一个功能强大的开源消息代理软件,提供了可靠的消息传递机制和灵活的集成能力,因此备受开发人员和系…...

PHP写一个电商 Api接口需要注意哪些?考虑哪些?
随着互联网的飞速发展,前后端分离的开发模式越来越流行。编写一个稳定、可靠和易于使用的 API 接口是现代互联网应用程序的关键。本文将介绍在使用 thinkphp6 框架开发 电商API 接口时需要注意的要点和考虑的问题,并提供详细的逻辑步骤和代码案例。 1. …...

微服务概览
单体架构 传统的软件应用为单体架构。尽管也是模块化逻辑,但是最终还是会打包并并部署为单体应用。最主要的原因是太复杂。并且应用扩展性低,可靠性也低。敏捷开发和部署变得无法完成。 治理办法:化繁为简,分而治之。 微服务起源…...

本地新建vs工程运行c++17std::varant
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:…...

GPON、XG(S)-PON基础
前言 本文主要介绍了GPON、XG(S)-PON中数据复用技术、协议、关键技术、组网保护等内容,希望对你有帮助。 一:GPON数据复用技术 下行波长:1490nm,上行波长:1310nm 1:单线双向传输(WDM技术&am…...

CSS实现图片滑动对比
实现效果图如下: css代码: 知识点:resize: horizontal; 文档地址 <style>.image-slider {position: relative;display: inline-block;width: 500px;height: 300px;}.image-slider>div {position: absolute;top: 0;bottom: 0;left: …...

苹果电脑录屏快捷键,让你成为录屏达人
“苹果电脑录屏好麻烦呀,操作步骤很繁琐,有人知道苹果电脑怎么快速录屏呀,要是有快捷键就更好了,大家知道苹果电脑有录屏快捷键吗?谢谢啦!” 苹果电脑以其直观的用户界面和卓越的性能而闻名,而…...
9.2 Plotting with pandas and seaborn(用pandas和seaborn绘图)
9.2 Plotting with pandas and seaborn(用pandas和seaborn绘图) matplotlib是一个相对底层的工具。pandas自身有内建的可视化工具。另一个库seaborn则是用来做一些统计图形。 导入seaborn会改变matplotlib默认的颜色和绘图样式,提高可读性和美感。即使不适用seaborn的API,…...

01序列 卡特兰数
解法: 将01序列置于坐标轴上,起始点为原点。0表示向右走,1表示向上走。这样就可以将前缀0的个数不少于1的个数就可以转换为路径上的点,横坐标大于纵坐标,也就是求合法路径个数。 注意题目mod的数是质数,所…...

java实现快速排序
图解 快速排序是一种常见的排序算法,它通过选取一个基准元素,将待排序的数组划分为两个子数组,一个子数组中的元素都小于基准元素,另一个子数组中的元素都大于基准元素。然后递归地对子数组进行排序,直到子数组的长度为…...

【Spring Boot】034-Spring Boot 整合 JUnit
【Spring Boot】034-Spring Boot 整合 JUnit 文章目录 【Spring Boot】034-Spring Boot 整合 JUnit一、单元测试1、什么是单元2、什么是单元测试3、为什么要单元测试 二、JUnit1、概述简介特点 2、JUnit4概述基本用法 3、JUnit5概述组成 4、JUnit5 与 JUnit4 的常用注解对比 三…...

基于安卓android微信小程序的师生答疑交流平app
项目介绍 本课题研究的是基于HBuilder X系统平台的师生答疑交流APP,开发这款师生答疑交流APP主要是为了帮助用户可以不用约束时间与地点进行所需信息。本文详细讲述了师生答疑交流APP的界面设计及使用,主要包括界面的实现、控件的使用、界面的布局和异常…...
开发一个接口,需要考虑什么
开发一个对外接口,一般会考虑以下因素: 用户需求:首先要考虑用户的需求,了解他们希望通过接口实现什么样的功能,以及他们期望接口具备怎样的特性和性能。 可扩展性:接口需要具备良好的可扩展性,…...
【owt】owt-p2p的vs工程构建
owt的p2p代码构建一个静态库 Build started... 1>------ Build started: Project: owtTalkP2P, Configuration: Debug Win32 ------ 1>p2ppeerconnectionchannel.cc 1>g:\webrtc_m98_yjf\src\media\base\codec.h : warning C4819: The file contains a character that…...
uniapp系列
MQTT: 1、报错:TypeError: WebSocket is not a constructor 背景:最近使用MQTT协议传递消息,集成在uniapp上,出现此问题 解决:app端需要用"wx://"(安全协议用"wxs://"&a…...

AWS实战(一)-创建S3 存储桶
1)登录AWS账号,选择服务—>存储—>S3。 2)查看存储桶列表 3)点击"创建存储桶"创建bucket。 4)设置跨域 点击编辑,修改跨域设置即可。...

Java实现简单的俄罗斯方块游戏
一、创建新项目 1.首先新建一个项目,并命名为俄罗斯方块。 2.其次新建一个类,命名为Main,或其他的。 二、运行代码 代码如下: package 俄罗斯方块;import java.awt.BorderLayout; import java.awt.Color; import java.awt.Gr…...

深度学习+opencv+python实现车道线检测 - 自动驾驶 计算机竞赛
文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络3.1卷积层3.2 池化层3.3 激活函数:3.4 全连接层3.5 使用tensorflow中keras模块实现卷积神经网络 4 YOLOV56 数据集处理7 模型训练8 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 &am…...

人工智能 :一种现代的方法 第七章 逻辑智能体
文章目录 前言人工智能 :一种现代的方法 第七章 逻辑智能体7.1 基于知识的智能体7.2 Wumpus世界7.4 命题逻辑7.5 命题逻辑定理证明7.5.1推导和证明7.5.2 归结原理7.5.3 horn子句和限定子句7.5.4 前向链接和后向链接 7.6 有效命题逻辑模型求解7.6.1完备的回溯算法7.6…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...