这是 Jerry 2021 年的第 54 篇文章,也是汪子熙公众号总共第 331 篇原创文章。
任何企业级软件的前端开发,都离不开组件(Component)这个概念。撇开具体的 UI 开发技术不谈,所谓组件,就是界面的组成部分(UI Building Blocks). 组件在视觉或者业务功能上,能够被视为单一元素。
组件可能被构成应用程序的其他组件重用,也可能包含其他组件。理想情况下,一个设计良好的组件,其同其他组件或者外部服务的依赖关系,可以被恰当地隔离,从而能够单独对组件进行单元测试甚至自动化测试。
近些年随着微服务架构浪潮而兴起的微前端设计理念,甚至支持同一应用内不同的 UI 组件,采取不同的前端技术进行开发,这些异构的 UI 组件,可以独立地进行开发,测试,部署和交付,通过统一的微前端容器进行管理,并构成最终由用户使用的前端程序。
Luigi 就是 SAP 推动的一个微前端框架。
微前端框架的使用已经超出了本文讨论的范畴。本文就 SAP 下列四种产品所使用的前端开发框架/工具中包含的组件概念,展开进行介绍。
SAP CRM / SRM
SAP S/4HANA
SAP Cloud for Customer
SAP Commerce Cloud
本世纪初,随着企业应用软件从 Client/Server 模式往 Browser/Server 模式的迁移,SAP CRM 和 SAP SRM 的前端开发技术,也踏上了不同的两条演进道路:分别基于 SAP WebClient UI 和 ABAP Webdynpro. 关于这两项技术更多的介绍和 SAP UI 开发技术的演进之路,请参考 Jerry 之前的文章:SAP UI 和 Salesforce UI 开发漫谈。
SAP WebClient UI 的前身是 SAP BSP - Business Server Page.WebClient UI 在其基础上,引入了组件的概念,并且在视图层增添了对 BSP 扩展标签库的支持,使得其开发效率大大提高。基于 SAP WebClient UI 的开发方式,至今仍在 SAP S/4HANA Service 模块领域中采用。
一个基于 SAP WebClient UI 的应用,通常由多个组件构成。单个组件的开发,仍然基于传统的 MVC,其中 Model 层的 Context Node,由 ABAP Class 实现,而 ABAP Webdynpro 中的 Context Node,采取的是 ABAP DDIC 数据字段中的数据结构。
WebClient UI 组件的视图层基于 HTML,能重用 SAP 标准 BSP Extension 中提供的 HTML 标签。绝大多数情况下,应用开发人员无需编写原生的 HTML 代码,这也降低了开发门槛。ABAP Webdynpro 组件视图层开发,在 SAP 提供的所见即所得的布局编辑器中进行,开发人员无法使用原生的 HTML 编辑方式开发视图。
WebClient UI 里有一类特殊的组件,起着容器的作用,负责将其包含的其他组件的视图按照用户配置显示出来。
下图是一个例子:SAP CRM 产品概览页面,左边红色区域,是该容器组件支持的所有组件和组件视图列表,右边是当前用户配置的该容器到底要显示哪些组件视图,及这些组件视图的加载方式:直接加载或者延迟加载。这种从一个支持组件列表里选择部分加载的配置方式,在本文后续介绍 SAP Commerce Cloud 组件时会再次提及。
SAP S/4HANA
前文已经介绍过,SAP S/4HANA Service 模块的 UI,仍然基于 SAP WebClient UI 开发。Service 模块在 SAP 内部简称为 S4CRM,官方称谓为 S/4HANA for Customer Management,详情参考 Jerry 的文章:Hello World, S/4HANA for Customer Management 1.0.
SAP S/4HANA 除了 Service 之外的其他模块,其 UI 通过 SAP Fiori Elements 开发,该框架后台模型为加上了注解的 SAP CDS view 即暴露给外界消费的 OData 服务,前台开发框架为 SAP UI5. Component.js 是所有配置到 SAP Fiori Launchpad 中的 SAP UI5 应用的入口。
以 SAP S/4HANA Sales Management Overview 这个 Fiori 应用为例:
和其他所有基于 Fiori Elements 开发的应用一样,Sales Management Overview 应用工程内仅包含一个 Component.js, 该文件内声明了对 manifest.json 文件的引用。其余在 Freestyle SAP UI5 开发模式下需要应用开发人员编写的 Controller,View 等资源文件,在 Fiori Elements 应用里均被 SAP UI5 框架提供的模板版本所取代。
在 manifest.json 文件里,我们能得到下列这些信息:
该 Fiori 应用消费的 OData 服务名称,SD_OVP_SM
该 Fiori 应用消费的 OData 服务基于的 CDS view 名称:C_PROFITMARGINBYMONTHQUERY_CDS
Fiori 应用 ID:F2601
有了 F2601 这个 Fiori ID 之后,从 Jerry 文章 SAP Fiori应用索引大全 里介绍的网站上,根据该 ID,即可查询到该 Fiori 应用的设计详情:
关于 SAP Fiori Elements 应用 manifest.json 更多的细节介绍,请参考 Jerry 之前的文章:
在没有任何前端开发经验的基础上, 创建第一个 SAP Fiori Elements 应用
答网友提问:使用 SAP Fiori Tools 创建的 Fiori Elements 应用,如何进行二次开发?
关于 SAP Fiori Elements 开发的更多介绍,可以参考 Jerry 翻译的 OpenSAP 上的公开课。由于工作繁忙,目前只完成了前四期视频的翻译工作:
OpenSAP Fiori Elements 公开课第一单元:总体介绍
OpenSAP Fiori Elements 公开课第二单元:架构介绍
OpenSAP Fiori Elements 公开课第三单元:OData 服务和注解介绍
OpenSAP Fiori Elements 公开课第四单元:开发环境搭建
SAP Cloud for Customer
同 ABAP Webdynpro 一样,SAP Cloud for Customer 的组件开发,也是在所见即所得的编辑器里进行,这个编辑器叫做 UI Designer.
如果说 SAP Fiori Elements 是基于 CDS view 以及 OData 服务进行的组件开发,那么 SAP Cloud for Customer 的组件开发则是基于 Business Object 驱动的。
开发人员使用 SAP Cloud Application Studio 完成 Business Object 模型创建后,可以使用向导,一键生成针对该 BO 进行增删改查操作的全套 UI.这些 UI 类型各异, 由不同的组件所实现。
打开任意一个 UI 组件,发现其仍然分为 MVC 三层。其中视图层,开发人员可以在 Toolbox 面板中拖拽合适的 UI 控件,以所见即所得的方式设计视图;
在模型层,选择 C4C 标准的 BO 或者 Partners 二次开发的 BO, 可以完成视图控件字段同 BO 字段的数据绑定;
在控制器层面,可以采用非编码的声明方式,指定该视图响应用户操作之后,应该执行何种业务逻辑。
由于历史原因,SAP C4C 用户访问入口,并不是像 S/4HANA 那样采用了 Fiori Launchpad,而是同 SAP CRM 一样,选择工作中心(Work Center)作为入口。
用户被分配的业务角色(Business Role)决定了其能够访问的工作中心。C4C 的 UI 组件被添加到工作中心视图中,后者再被添加到工作中心内,从而被用户访问。
因为并未通过 Fiori Launchpad, 进行管理,所以 C4C 组件也就不存在 Component.js. 每个 C4C UI 组件本质上是一个 XML 文件,该文件存储在 C4C 后台一个叫做 X-Repository 的基础设施上。
运行时当所属的工作中心视图被访问时,UI 组件的源代码从 C4C 后台加载到浏览器,被 SAP UI5 框架解析。后者按照 C4C 特有的视图格式,根据组件源代码里包含的控件定义内容,创建对应的 UI5 控件实例。这些控件实例再使用对应的渲染器,按照文章 深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器 里介绍的逻辑,生成最终的原生 HTML 源代码。
传统的 SAP UI5 应用里,UI5 框架基于 JavaScript 或者 XML 视图文件,创建对应的 SAP UI5 控件实例。而 C4C 则是基于组件视图文件,进行控件实例化,这算是 C4C 组件使用 SAP UI5 的独特之处。
关于 C4C 组件设计的更多细节和其与 SAP UI5 框架交互的深入分析,请参考我的同事 Yang Joey 的文章: SAP Cloud for Customer 使用 SAP UI5 的独特之处。
SAP Commerce Cloud
SAP Commerce Cloud UI 作为 Headless Commerce 即无头电商架构的前端展现层,是一个 100% API 驱动的电商 Storefront:店铺待显示的组件列表,通过 API 调用的方式从 Commerce Cloud 后台端的内容管理系统(Content Management System,简称 CMS)中获取,而店铺具体显示的视图效果和与用户交互的逻辑,由前端基于 Angular 的组件实现。
以 SAP Commerce Cloud UI 打开后显示的默认主页为例,该页面的 id 为 homepage,其页面显示的内容列表,在 SAP Commerce Cloud Backoffice CMS 控制台中定义。
SAP Commerce Cloud 中一个页面被划分成若干个区域,这些区域被所谓的 ContentSlot(内容插槽)来区分,这个名称很形象——每个内容插槽,允许插入一个或者多个组件。
在 CMS Page 编辑页面里,点击 Content Slots 面板,定义该页面由哪些内容插槽组成:
下图展示了 homepage 由内容插槽 Section1, Section2A,Section2B,Section2C 等区域组成。
一个 Content Slot 可以容纳多个组件,下图展示了 Section1 这个 Content Slot,容纳 Electronics Homepage Splash Banner Component 和 Electronics Homepage Splash Discount Component 这两个组件。
大家可以类比前文介绍的 SAP CRM 容器组件,用户可以指定容器组件内显示哪些其他组件的视图,二者的设计思路是一致的。
SAP Commerce Cloud CMS 只负责定义页面的 Content Slots 信息和 Content Slots 内包含的组件信息,而不负责具体的页面视图开发以及用户交互逻辑开发——后者均是由 Jerry 所在的团队,开发的 SAP Spartacus 这个开源项目里实现。
每一个在 SAP Commerce Cloud CMS 中定义的组件,在 SAP Spartacus 中都有一个与之一一对应的 Angular 组件。
当在浏览器中打开 SAP Commerce Cloud UI 时,SAP Spartacus 会发起一个 API 调用,向 Commerce Cloud 后台索取该页面的 CMS 信息。下图展示了 homepage 在 CMS 中的建模信息,通过 API 调用的方式返回给 SAP Spartacus:
其中 Section1 这个 Content Slot 里包含的两个 Components 名称,正是我之前在 Commerce Cloud CMS 里维护的两个 Component:
SAP Spartacus 接收到这些 API 响应后,解析出 CMS Component 的名称以及与其一一对应的 Angular Component 的名称,将后者动态渲染出来。
下图是 SAP Commerce Cloud 默认的主页:
如何才能知道其中哪个区域,代表我前文提到的内容插槽 Section1,及放置在其中的两个组件呢?
我在 SAP Spartacus 渲染 Content Slots 中放置的组件代码位置处,加上了一些调试信息,打印出了 Slot ID 和 Component ID,便于大家理解:
刷新 SAP Commerce Cloud 页面:
根据页面上打印的调试信息,一目了然,下图黄色高亮部分,代表 ID 为 Section1 这个内容插槽在页面上的起始位置。绿色高亮为 Section1 包含的两个组件的 ID,而红色及蓝色矩形框,代表的是这两个组件被 Angular 渲染后的最终显示效果:
总结
本文概述了 SAP CRM,SAP S/4HANA,SAP Cloud for Customer 和 SAP Commerce Cloud 这四个产品中前端 UI 开发中使用到的组件理念。虽然具体实现技术不同,但这四个产品前端的组件,都体现了对各自完成功能的封装,以及作为应用程序前端界面构建块的用途。
由于篇幅所限,本文没有办法针对每个产品逐一展开深入介绍,大家可以使用我这篇文章 如何高效搜索汪子熙公众号发表的文章 介绍的搜索功能,搜索本公众号之前发布的文章,以对这些产品的 UI 开发技术进行深入了解。
感谢阅读。