From 5368800e88dab799ee4a2c3dc3ad455a669d5f9a Mon Sep 17 00:00:00 2001
From: ascoders <576625322@qq.com>
Date: Mon, 9 Jan 2023 10:01:11 +0800
Subject: [PATCH] 268
---
helper.js | 1 +
readme.md | 6 +-
...26\346\220\255\345\273\272\343\200\213.md" | 103 ++++++++++++++++++
3 files changed, 109 insertions(+), 1 deletion(-)
create mode 100644 "\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272/268.\347\262\276\350\257\273\343\200\212\345\246\202\344\275\225\346\212\275\350\261\241\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272\343\200\213.md"
diff --git a/helper.js b/helper.js
index 8f58889a..07b59774 100644
--- a/helper.js
+++ b/helper.js
@@ -13,6 +13,7 @@ const dirs = [
"源码解读",
"商业思考",
"算法",
+ "可视化搭建",
"SQL"
];
diff --git a/readme.md b/readme.md
index 7d9c5254..28f1e272 100644
--- a/readme.md
+++ b/readme.md
@@ -6,7 +6,7 @@
前端界的好文精读,每周更新!
-最新精读:267.精读《磁贴布局 - 性能优化》
+最新精读:268.精读《如何抽象可视化搭建》
素材来源:[周刊参考池](https://github.com/ascoders/weekly/issues/2)
@@ -299,6 +299,10 @@
- 201.精读《算法 - 二叉树》
- 203.精读《算法 - 二叉搜索树》
+### 可视化搭建
+
+- 268.精读《如何抽象可视化搭建》
+
### SQL
- 231.SQL 入门
diff --git "a/\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272/268.\347\262\276\350\257\273\343\200\212\345\246\202\344\275\225\346\212\275\350\261\241\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272\343\200\213.md" "b/\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272/268.\347\262\276\350\257\273\343\200\212\345\246\202\344\275\225\346\212\275\350\261\241\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272\343\200\213.md"
new file mode 100644
index 00000000..a6f1ca43
--- /dev/null
+++ "b/\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272/268.\347\262\276\350\257\273\343\200\212\345\246\202\344\275\225\346\212\275\350\261\241\345\217\257\350\247\206\345\214\226\346\220\255\345\273\272\343\200\213.md"
@@ -0,0 +1,103 @@
+在做任何可视化搭建项目时,第一步都要思考如何抽象。
+
+如果不抽象,当搭建项目做到后期可能会出现 API 杂乱,难以维护的问题;做到一半甚至会怀疑为什么需要一个搭建框架,怀疑把框架去掉会不会效率更高;在后期发现不能自然的水平拓展到仪表盘、大屏、表单搭建场景等。
+
+所以如果在维护一套可视化搭建系统时,不管这个系统的上层是 BI、大屏、表单填报,还是脑图也好,无论是什么,都要先思考一下这些系统背后的底层是什么,需不需要抽象,抽象的意义和价值在哪。
+
+以下结合笔者的经验,尝试给出一种思考角度。
+
+## 精读
+
+### 什么是可视化搭建
+
+表单搭建、中后台应用搭建、BI 仪表盘搭建、大屏搭建都算可视化搭建,因为它们都是在一个画布上拖拖拽拽完成的。
+
+那么组件配置表单算搭建吗?聚焦单组件分析的可视化探索呢?幻灯片呢?
+
+比如组件配置表单,它基于 UI 组件树抽象的话,就是可视化搭建,但如果基于表单结构抽象,就是 JsonSchema,但真的所有业务场景都是数据完全映射 UI 吗?不一定,因为 UI 可以为了用户操作方便而加入更多辅助元素,甚至把一个属性拆成多个 UI 填写,所以基于可视化搭建,也就是 UI 组件树抽象的一定可以覆盖所有表单场景,但不一定是描述效率最高的方式。
+
+如果每种可视化搭建场景都定义一套协议与实现,那按照搭建平台的复杂度,想同时维护两个类搭建平台的成本一定是两倍,而且不同维护人员很难交流。又或者某些可以按照搭建思路解决的场景,因为实现时经验不足,没有进行抽象,甚至进行了另一套定制抽象,回过头来看可能积重难返,团队不得不接受多套笨重实现的现状。
+
+所以建议将这些场景都视为可视化搭建场景,用一套接口描述结构、API 方法,让看似百花齐放的编辑器之下拥有统一的上下文与实现。
+
+### 可视化搭建的分层
+
+对于不同种类的可视化搭建平台,我们尝试寻找其分层设计的最大公约数。如果把可视化搭建底层设定为逻辑层,即这个层是 UI 无关的,仅关心组件树结构、逻辑功能,那么对于每种平台的分层应该是这样的:
+
+1. 表单搭建:逻辑层、表单联动协议层、表单控件、业务层。
+2. 中后台应用搭建:逻辑层、应用联动协议层、应用控件、业务层。
+3. BI 仪表盘:逻辑层、筛选联动协议层、可视化控件、业务层。
+4. 大屏搭建:逻辑层、画布编辑控制器层、可视化控件和基础图形控件、业务层。
+
+最底层的逻辑层应该可以统一所有类型搭建系统,并成为开发人员统一上下文的。它可以包含以下基础能力:
+
+1. 定义组件树结构。
+2. 定义组件元信息。
+3. 按照组件树结构递归渲染画布。
+4. 支持布局、取数、联动、筛选、校验等一系列拓展能力,业务可根据需要定制。
+5. 提供所有业务层都需要的能力,比如性能优化的组件冻结、状态管理、对组件树增删改查的 API。
+
+在逻辑层完备后,再开发上层应用就会轻松很多,只要注册组件、根据业务需要在组件树初始化或组件初始化,或组件元信息注册时添加定制逻辑,与系统功能对接,并补充业务特色的如自定义布局能力,这样就可以用简单的三言两语说清楚整个系统是如何设计的。
+
+### 逻辑层存在的必要性
+
+再回到问题的根源:对逻辑层做统一的抽象到底是不是多余的?
+
+要回答这个问题,需要先了解我们手头里有哪些工具:基础开发工具 html、js、css,并且 html 也提供了一套标准化的 xml 结构;vue、react 等开发框架,基础组件、应用生命周期与事件定义。理论上基于这些,我们就可以直接上手写一个可视化搭建平台了,似乎也可以不抽象。但真正要上手时,一定会遇到以下几个通用问题需要处理:
+
+**定义组件树结构**
+
+无论做表单搭建、报表搭建、大屏搭建还是脑图画布,第一个想到的肯定是如何描述这个画布结构,而无论画布是横着排还是竖着排,横竖都是一棵树。HTML 树不能直接搬过来,一是 HTML 树的完整结构太大而我们需要的更精简的结构,二是业务层框架一般都先有一套虚拟树再转化为 dom 树,因果关系也没法反过来。而这棵树也完全可以做最大程度的抽象,即定义组件 ID、组件名、属性(Props)、子节点。
+
+**定义对组件树增删改查函数**
+
+有了组件树肯定需要对其进行增删改查操作,因为无法基于 document API,上层框架如 vue、react 也不提供对任何标准组件树的增删改查 API,这部分能力势必要手动实现。
+
+**生命周期**
+
+假设完全依赖 React 框架提供的组件生命周期,是可以完成大部分业务逻辑,但这意味着定义不够精细化。比方说,我们在组件 Mount 的实际监听了联动、实现取数、设置冻结等等效果,虽然也可以实现,但会遇到要不要抽象的问题:
+
+- 如果不抽象,业务代码就会乱糟糟的,比较难读。
+- 如果抽象,就要把联动、取数、冻结等等模块归类,封装成函数,甚至可以提供主动调用机制,UI 与逻辑解耦,但当业务层精细的去做这件事就会发现,这就是在做框架层的抽象工作,所以还不如一开始就把这些生命周期抽象到框架里。
+
+逻辑层有两个核心结构,第一个是组件树结构,包含了对每个组件实例的定义;第二个是组件元信息结构,包含了对每个组件的元信息描述,大概如下图所示:
+
+
+
+逻辑层的难点就是在元信息定义足够多、足够通用的生命周期回调函数,并且这些回调函数还能尽可能的功能正交。
+
+**组件渲染**
+
+通常一棵树按照 json 结构描述自顶向下自动渲染就可以了,但也有一些时候,比如内嵌一个富文本组件,而富文本内又嵌入一些画布组件,这些组件需要像普通画布组件一样可交互,此时就有 **渲染一个不存在于组件树的组件实例** 的需求,而这样的动态组件又要无感知的满足上面所说的各类生命周期,这也是不小的工作量。
+
+**功能的拓展抽象**
+
+等可视化搭建平台正式维护时,就至少会遇到组件版本升级、不同类型的布局方案对接、三方组件注册等需求,这些功能如何加入到现有的搭建平台,而不让其他功能感知,是需要精心设计的。如果逻辑层把这一点抽象好,在每个功能设计一个钩子,实现一个功能时无需感知其他功能,那平台的功能拓展就会保持一个恒定的速度,不随功能增加而变得难以维护。
+
+可见,可视化搭建不断迭代的过程就是自身不断抽象的过程,逻辑层实现的好坏直接影响到后期的维护性与拓展性,所以好好设计逻辑层可以让开发事半功倍。
+
+### 组件配置表单要不要用搭建方案做
+
+组件配置直接用表单方案而不是搭建,似乎是最容易想到的。但当每个组件都要自定义配置,我们就不得不选择基于 JsonSchema 描述的表单方案,但这与搭建应用本身的技术栈割裂了,随着联动功能的要求越来越多,会越来越发现小小的表单渲染引擎维护得越来越复杂,甚至复杂度与画布不分上下,此时再叹息两边技术栈不统一就已经晚了。
+
+换个角度想一下,搭建应用不也要考虑组件间联动吗?从表单值能力来看,搭建场景并不要求每个组件都拥有一个值,反倒是可以将组件任意 props 属性看作表单值更具有 “弹性”,我们可以拓展任意 Key 作为表单值。
+
+另外,从数据结构触发来描述表单看似很美好,但当表单变得越来越复杂,UI 越来越定制后,势必引入新的 UI 节点或者新的结构描述,与其后期拓展到一个不纯净的 JsonSchema 结构,不如一开始就放弃这个幻想,用 UI 组件树结构描述表单,这样事情就变得简单了:“先描述组件树,再定义每个节点分别用什么组件渲染,响应表单的哪部分 Key”。
+
+## 总结
+
+总结一下,回到主题,抽象可视化搭建的方法是分层:以逻辑层打底,提供一套标准规范与 API 接口,上层注册组件、实现布局,一切围绕着标准化的逻辑层进行拓展。
+
+而可视化搭建的每一层都可以分别写单元测试,保证最终变化的代码只有业务层的对接部分,应用的稳定性就提高了。
+
+最后提一个思考题:你是觉得可视化搭建应该如何抽象?如果想要做到每一层独立正交,你会如何设计 API 呢?
+
+> 讨论地址是:[精读《如何抽象可视化搭建》· Issue #463 · dt-fe/weekly](https://github.com/dt-fe/weekly/issues/463)
+
+**如果你想参与讨论,请 [点击这里](https://github.com/dt-fe/weekly),每周都有新的主题,周末或周一发布。前端精读 - 帮你筛选靠谱的内容。**
+
+> 关注 **前端精读微信公众号**
+
+
+
+> 版权声明:自由转载-非商用-非衍生-保持署名([创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh))