可视化开发:前端按时下班不再是问题
摘要: 如何快速、高效地构建前端组件乃至页面是解放前端生产力的重要标志,掌握抽象组件和页面模型,理解前端可视化搭建思路,摆脱固有的开发模式,提高前端开发效率,是每位前端应该了解的。
本文分享自华为云社区《【云驻共创】前端可视化框架是怎样炼成的?》,原文作者:华为云 EI 专家胡琦。
随着移动互联网的迅猛发展和 5G 技术的普及,前端页面需求量爆炸增长,用户交互也变得越来越复杂,页面从零开发的成本也水涨船高。如何快速、高效地构建前端组件乃至页面是解放前端生产力的重要标志,掌握抽象组件和页面模型,理解前端可视化搭建思路,摆脱固有的开发模式,提高前端开发效率,是每位前端应该了解的。
从一个“栗子”说起
在我们前端开发过程中可能经常这样会遇到这样的场景:
当然,既然能想到通过 JSON 去配置,那意味着整个组件、页面都能配置,只需给到产品经理一个可视化的界面去配置,即可生成 TA 想要的页面,大大节省了沟通成本、提升了开发效率。这时,可视化框架应运而生。
可视化框架的构成和分工
可视化框架是怎样的?首先我们先了解一下可视化框架的构成和分工。开发作为可视化框架的维护者,可以提供一个可视化的配置平台;目标受众,也就是可视化平台的使用者,如上文例子中的产品经理;使用者通过可视化配置平台对页面进行配置,平台会产出一份配置文件用来描述页面并上传到存储空间;配置文件通过渲染引擎解析最终生成页面。在这个构成中,作为开发框架的维护者,我们只需要关注可视化配置平台和渲染引擎,当然可视化配置平台也只是将使用者的输入转化为渲染引擎能解析的配置文件并上传,是锦上添花的一环,如果还想应用在更复杂的场景,还可以加上权限管理,比如 A 只能编辑 A 负责的页面,B 只能编辑 B 复制的页面,还可以实现一个工作流的流程编排,比如审核……
可视化框架的核心在于渲染引擎,我们如何得出这个渲染引擎以及渲染引擎是如何运作并渲染最终的页面,是我们所关心的。如何得出渲染引擎就不得不先说说页面泛化模型。
页面泛化模型
为什么会有页面泛化模型?因为我们不同的页面其实是通过渲染引擎解析不同的配置文件渲染出来的,因此渲染引擎需要泛化的能力。比如页面 A 是表单填写,那么就会要求渲染引擎能够解析表单的配置文件;比如页面 B 包含卡片式列表,就会要求渲染引擎能够解析列表的配置文件。页面泛化模型的建立,主要根据开发者自身的经验和方法建立满足自身业务需求的模型即可。像上文案例中,如果产品经理一直只要求修改欢迎词,那案例中的那段 title 的渲染引擎就足够满足需求了。接下来,以华为云官网页面为例,抛砖引玉讲讲页面泛化模型如何建立。
从上面截图中我们可以看出这其实是一个从上到下的结构,可以理解为页面是由一个个楼层构成的,楼层可以理解为 body 下的一个 div 块,或者是一个功能块。比如图中从上到下是页头、banner、引导跳转楼层、推荐文章、技术领域楼层。当然我们经常遇到的页面也不全都是上下结构,还有左右结构。
其实,像这样左右结构的页面,您可以理解外层还有一个更大的容器组件包裹,整体形成一个楼层。容器组件只负责样式,比如上图中容器组件负责左右布局,如果您对布局还没有概念,您可按下 F12 键查看上图布局的代码,您会看到其实左边两个模块是被 classname 为 edu-index-version-left 的 div 包裹,右边两个模块是被 classname 为 edu-index-version-right 的 div 包裹,它们依旧是从上到下的楼层。因此,页面 = 楼层 + 容器组件。
再来看看楼层解构,以上图为例,图中主体部分是一个 tab 功能组件,通过查看页面源码,我们发现两处红色框圈出来的文本并没有设计在 tab 功能组件里,而是单独成为文本控件,这是因为这部分是属于定制化的功能,并不是每个 tab 功能组件都有的,就抽离出来了遵循单一职责原则,蓝色框是一个容器组件。再来看看 tab 功能组件中的卡片,卡片也是由一个一个的控件组成。因此,楼层=容器组件 +控件。
可视化框架中的控件和常见的 UI 框架中的组件一样,都具有完善且单一的职责,比如表格组件,无论再怎么加功能都是在表格内部,表格里面的功能是无法拆分出去的。但可视化框架中的控件和 UI 框架中的组件还是有区别的,主要不同点在于控件需要用来被编辑,因此它具有统一的 props,所有的控件要遵循一样的 props,如视图配置和数据源,在可视化中我们不知道页面会用到哪些组件,因此需要统一去做循环渲染,不感知控件的具体属性。
可视化框架中的容器组件本质上也是组件,主要负责布局,分为基础容器组件和功能容器组件。基础容器组件中左右布局一般通过栅格或者 Flex 实现,上下布局通过正常的文本流或者定位以及控件自身间距等实现。功能容器组件如 tab 容器、轮播组件等。
当考虑用户交互时,事件在可视化模型中就不得不考虑。可视化模型中的事件需要关注交互的发起者、交互的作用者以及交互的影响方式,而不需要关注交互的种类和交互的具体内容。比如点击了某个按钮,步进器的最大最小值从 1、2 变成 3、4,其实是改变了 input 控件的 min 和 max 属性;比如表格筛选加了一定条件之后,显示数据变少了,是因为触发了数据事件影响了表格的数据源;比如一个开关组件,点击之后控制控件的显示和隐藏……
最终,我们确定的可视化模型就是上图中总结的点。可视化页面由控件 + 容器组件 + 事件组成,控件的粒度最小,是功能的最小单位;容器组件负责布局,是样式的集合;事件响应用户交互传递控件间依赖关系。那控件、容器组件、事件是怎么结合的呢?就不得不谈谈渲染引擎了。
渲染引擎
渲染引擎本质上也是组件,主要功能是渲染当层组件、处理当层组件交互关系、对当层组件状态进行管理。它不关注子层组件,子层组件由子层容器的渲染引擎渲染,因为每一层组件的配置和数据源不一样,因此渲染结果也不相同。视图部分示例代码(基于 Vue.js)如下:
最外层是由 div 包裹,使用自定义动态组件 component 的方式定义渲染引擎,带下划线的属性意味着是自定义组件的内置属性,is 决定组件渲染的类型,如 button,做到可以不感知当层组件具体内容渲染当层组件;v-for 循环当前组件的属性;v-show 控制组件是否显示,通过 showState 进行状态管理;ref 建立索引,可以用来做一些高级功能,比如父层容器调用子层容器的方法;viewConfig 和 dataSource 就是上文中提到的控件中所必需的;@valueChange 是组件提交的统一事件。
父层容器和子层容器本质都是渲染引擎,只是样式不同。比如说一个左右布局的容器组件,相当于在视图中 v-for 循环的地方绑定一个 class 如栅格布局或者 flex 布局的样式,如果是栅格布局的话,用户就要先定义 type 是栅格组件,然后配置 viewConfig 中 grid 属性之类的,如果是 flex 布局,定义的 type 就是 flex 组件,对齐方式如指定为 space-between 之类的。上文中示例代码就是一个正常的从上到下的布局。
首先外层传递两个关键的参数--viewConfig 和 dataSource,当层容器就会进行配置解析和配置分发。配置解析主要包含属性映射和生成事件,属性映射比如控件本身需要 title 属性,而配置文件中可能是叫 label 属性,这时我们要将 label 转换成 title,只不过转换逻辑不包含在渲染引擎中,只是调用外部封装好的方法;生成事件则是根据配置生成预设事件并挂载。在配置分发之前,会先将解析好的配置进行初始化父层状态并存放在父层,主要考虑到 viewConfig 和 dataSource 不是同步赋值,需要等待都就绪了才进行分发。
在介绍控件的时候,提到每个控件都要提交,因为每个控件都不能成为其他控件的一个 origin。比如 Tip 组件,虽然本身可能没有交互,但可能成为别的控件的依赖项,子层可能需要获取内容,子层容器的提交会被收集在父层容器的 valueWatch 中,在子层容器提交以后,如果状态变化的话,那父层容器就会根据 functionList 去循环执行的事件;如果是展示类事件,就会更新父层的 showState 控制显示或隐藏,如果是数据类事件,则会改变 viewConfig 和 dataSource,对目标进行一个重新赋值。 总得来说渲染引擎流程就包含以上四个步骤:配置解析、配置分发、收集提交、发起事件。
总结
为了减少页面开发代码量,提升代码复用度,我们期望页面能进行可视化编辑;为了得出一个通过的可视化框架,我们对页面进行了可视化建模分析,得出几乎所有的页面都可以由控件和容器组件构成,通过泛化的事件处理用户交互和组件间的级联关系;根据建模的结果建立了渲染引擎,支撑起整个流程,最终实现可视化。
本文整理自华为云社区内容共创活动第二期之【线上直播】2.0 倍起步?高效完成前端页面。
查看活动详情:https://bbs.huaweicloud.com/forum/thread-111494-1-1.html
版权声明: 本文为 InfoQ 作者【华为云开发者社区】的原创文章。
原文链接:【http://xie.infoq.cn/article/c9aeb6432daa7e4f7a934c86d】。文章转载请联系作者。
评论