首发于前端拾碎

云凤蝶自由画布之道:分层模型

概述

云凤蝶是一个 hpaPaaS,目标是为中后台应用研发提供简单、高效、高质量的研发方案。在云凤蝶的自由画布、属性面板和数据驱动等特性的支持下,不仅是前后端,甚至 PD、设计师都能直接参与研发工作。

这篇文章就来分享下,云凤蝶的自由画布之道。


在云凤蝶的自由画布里,一切都是分层的。最底下是诸如 antd 等画布组件的渲染层,往上是错误报告层、框选层、右键菜单层、对齐线层、间距线层、选中/锁定边框等等非常多的交互层。

例如,画布的交叉错误红色警告、参考线、标尺:


选中/锁定边框:


右键菜单:


直观上看,交互层是这样的结构:


这种结构是云凤蝶自由画布迭代了无数遍之后沉淀下来的。它把画布从顶层划分成了渲染和交互两个方面。渲染层只负责把组件渲染到画布上,而交互层才是真正承载用户操作的地方,实现复杂业务功能的分层治理。


渲染层

云凤蝶画布的渲染层只负责组件渲染一件事,它不涉及用户操作。

画布组件都由 HOC 高阶组件包裹过,这个高阶组件做两件事情:

  1. 传递真实的 props 给画布组件
  2. 响应用户配置数据变化

交互层

云凤蝶画布的交互层真正承载了与用户的交互,比如错误报告、参考线等信息展示,框选、右键菜单等点选操作。


PositionMonitor 和 EventBus

真实业务场景里,用户和画布会产生非常多非常细的交互过程:

  1. 用户点击鼠标的时候,画布要知道用户点了哪个组件
  2. 用户框选组件的时候,画布要知道框选了哪些
  3. 组件所在位置上要渲染参考线、报错信息等,而且拖拽组件的时候信息能跟随拖拽
  4. ...

基本所有的交互都依赖一些关键信息:

  1. 画布组件的坐标
  2. 用户在组件上产生的 event 事件,比如 MouseEvent、DragEvent 等

而画布的交互层抓取到这些信息后,就可以做相应的操作了。这实际上是个渲染层和交互层通信和状态共享的过程,所以画布设计了 PositionMonitor 和 EventBus 来处理,如下图所示:


EventBus 是个经典的事件总线。用户的交互事件默认作用到了画布组件渲染层。渲染层通过 EventBus 抛出事件给交互层。交互层接到事件后进行自己的业务操作。

PositionMonitor:基于浏览器 MutationObserver 的画布组件坐标收集机制。当画布组件位置变化时,就会触发 PositionMonitor 调用 getBoundingClientRect 方法,收集组件坐标。


可观察模型驱动视图

画布的交互性要求非常高,各种交互状态要及时响应。比如组件拖拽的时候,对齐线、间距线、等距线等都要高性能实时绘制,否则会产生拖拽卡顿感。

React 经典的浅比较 props 自顶向下更新虚拟 dom 的方式已经不太能满足画布复杂状态下也要保持高性能的需求,所以画布组件内部同样采用了云凤蝶可观测 DDD 充血模型驱动视图的机制。

云凤蝶的模型驱动视图机制:定义一个可观测的 DDD 充血模型,当模型数据改变时,相应的 React 组件自动 forceUpdate 更新视图。这种方式可以让 UI 视图精确响应数据变化更新。

工程实现上,每个层都可以对画布暴露可观察的 Model,然后画布会把这些 Model 引用统一挂到内部的 $model 属性上,架构就变成如下图所示:




$model 是画布的顶部属性,共享给了所有画布层,完成了两件事情:

  1. 层与层之间的状态共享
  2. 模型驱动视图精确更新画布层

只要画布层代码上访问了 $model 上的字段,云凤蝶就通过依赖收集知道了画布层依赖 $model 的字段,数据变化自然而然精确触发相应画布层的视图更新,而没有访问 $model 的画布层则不更新,避免性能损耗。


UI 视图堆叠模式

通常情况下,交互层视图会 100% 盖在渲染层上面,然后通过读取组件坐标来定点绘制交互所需要的信息。例如间距线、对齐线、框选线等。直观上看大概是这样:


这种视图堆叠模式能解决绝大部分的视觉需求,但为了达到更极致的视觉表现力,单一的视图堆叠模式还不够:

  1. 组件坐标收集过程有一定的延时。如果交互视图强依赖了组件坐标,那也会产生延时,直观上的体验就是交互视图跟随不流畅。
  2. 交互视图会始终覆盖在组件渲染层上方,做不到画布组件盖住交互视图的效果。例如,选中的组件外围要有蓝色的边框,而边框却被另一个组件盖在了下面,如下图所示。


为了达到更极致的视觉表现力,画布目前一共设计了 4 种视图堆叠模式:Layer、InstanceLayer、WrapperLayer 和 ToolBar,整体结构如下图所示。它们分别实现了交互视图的画布覆盖、组件覆盖、画布包裹、工具条展示功能。只要通过适当的组合,基本上可以实现任意复杂度的视觉需求。


在工程实现上,一个交互层可以同时应用多个视图堆叠模式:



结语

本文主要介绍了云凤蝶自由画布的分层模型。在分层的视角下,组件渲染和各种交互操作都分门别类依次码放在不同的画布层,达到了较好的维护性和较高的性能。

自由画布是低代码建站的重要武器,未来还将开放一键摆放、智能布局等更加傻瓜化的页面搭建能力。



未来已来,时不我待!

云凤蝶招聘前端、Java、PD、设计岗位,未来等你共创!

如果你感兴趣,欢迎联系 chenyu@antfin.com 或 shuai.shao@antfin.com

发布于 2019-12-17

文章被以下专栏收录