这是Jerry在2021年的第68篇文章,也是王子熙的第345篇原创文章公众号。在Jerry之前的文章中,他谈到了SAP产品UI开发中组件的概念。他提到,无论SAP产品UI基于什么开发技术,呈现给最终用户的视觉效果都是通过一些逻辑组件(Component)实现的。这些逻辑组件代表了对SAP产品向终端用户提供的交互功能的细粒度封装,例如查询订单的接口和创建订单的接口,在开发时通常在两个不同的组件中实现。这些UI组件通常包括模型层、视图层和控制器层,它们通过开源或SAP自研的UI框架进行交互和协同工作。在很多SAP产品的UI开发中,组件的定义和边界非常清晰,比如SAPUI5中的Component.js,SAPABAPWebdynpro和WebClientUI中的Component,SAPCommerceCloudAcceleratorUI中的JSPComponent,Spartacus中的AngularComponentUI。这些产品的UI开发工作主要是编写这些Components的代码。下图所示的SAPCloudforCustomerUIDesigner中的各类UI模型,例如OWL、QAF、FS等,都是UI组件的典型例子。此外,一些早期的SAP产品,如运行在SAPGUI中的SAPERP,有使用ABAPDynpro实现的接口,并没有明确提出UI组件的概念。但是ABAPDynproScreen和PAI/PBO逻辑的结合,从设计和功能上也形成了逻辑UI组件。本文以一系列SAP产品UI为例,介绍SAP产品UI开发领域的另一种重要的组件类型,我称之为容器组件。与上述包含特定界面和业务功能的UI组件相比,容器组件本身并没有呈现给最终用户的界面,而只是简单地充当容器,是容纳其他UI组件的组件。一些容器组件可能支持一些简单的控制逻辑编写,运行时可以根据开发者指定的条件动态决定它包含哪些UI组件应该显示。下面通过Jerry参与过的一些SAP产品UI开发工作的具体实例介绍SAPUI容器组件的概念和功能。SAPWebClientUI下图是基于SAPWebClientUI开发的SAPCRM产品详情页.红色区域代表普通的UI组件,绿色区域是容器组件,它决定了它在运行时应该显示哪些UI组件。启动事务代码BSP_WD_CMPWB,打开UI组件开发环境,查看ID为PRD01OV的商品详情页容器组件。下图是这个容器组件包含的UI组件列表。在运行时显示在产品详细信息页面上的实际内容是此列表的子集。SAPCloudforCustomer/SAPBusinessByDesignSAPCloudforCustomer与SAPCRM一样,使用WorkCenter和WorkCenterView的概念来实现权限控制。用户只能看到分配给他们的工作中心视图中包含的特定界面。对于开发人员来说,SAPCRM的工作中心只是配置表中的一些条目,而SAPCloudforCustomer中的工作中心和工作中心视图则成为了开发工具中可以看到和编辑的UI模型。一个工作中心包含多个工作中心视图,下图为例:点击上图所示的SalesOrder工作中心视图,可以看到工作中心视图包含一个OWLComponent:OWL是ObjectWork的缩写List,即如下图所示,为最终用户提供搜索界面的UI组件。这体现了SAP产品对交易处理的一贯思路:客户一般从SAP产品UI提供的交易数据搜索页面入手,从搜索结果中选择一项,浏览详情页面。SAPCloudforCustomer和SAPBusinessByDesign的搜索页面是由OWL类型的UI组件实现的,这些OWL组件放置在工作中心视图的容器组件中。SAPCloudforCustomer还有一类应用广泛且功能强大的容器组件ECComponent,即EmbeddedComponent,嵌入式组件。ECComponent作为容器控件,本身可以容纳其他UI组件,同时可以以紧耦合和松耦合的方式嵌入到另一个父组件中。在很多方面,包含在里面的UIComponent可以和嵌入的父组件之间进行数据传递和通信。借助SAPC4C的Mashup技术,ECComponent无论是在SAPC4C标准的制定,还是合作伙伴的二次开发,都有着广泛的用途。比如下图所示的SAPC4C的地图集成功能:以及我之前文章介绍的如何在SAPCloudforCustomer页面嵌入自定义UI的场景,比如我们可以部署第三方网站或者SAPBTP平台上自研页面通过ECComponent嵌入到SAPC4C标准UI中。SAP电商云SpartacusUI就是其中代表之一的基于无头电商(HeadlessCommerce)架构的解决方案。SAPCommerceCloudSpartacusUI页面的展示是用纯CMS驱动的思路完成的。CMS(ContentManagementSystem)管理员在SAPCommerceCloudBackoffice中定义要显示在电子商务云前台的页面内容。这些页面内容定义通过将它们公开为OCC(OmniCommerceConnect)API提供给SAPSpartacusUI使用。后者获取到需要展示的页面内容后,负责具体的视觉效果(VisualEffect)渲染。以SAP电商云首页首页为例,CMS管理员在首页中维护首页包含的ContentSlots(内容槽)。一个页面可以容纳多个内容槽,每个页面槽对应屏幕的一个区域。这些内容插槽根据显示内容将主页划分为几个区域,如HeaderSlot、FooterSlot、SiteLogoSlot、Section1Slot、Section2Slot等。每个内容槽中可以放置一个或多个CMSComponent,这里的CMSComponent充当占位符——CMS管理员并不关心每个CMSComponent显示的具体视觉效果,甚至这些CMSComponents,是否由其实现JSP还是Angular?下图显示了放置在内容插槽Section1Slot中的两个CMS组件的名称。SAP电商云加速器UI和SpartacusUI将分别使用JSPComponent和AngularComponent技术来实现这些CMSComponents。可以将CMSComponent放置在如下图Backoffice所示的contentslot中,AcceleratorUI和SpartacusUI中Components的关系类似于面向对象中接口与其具体实现类的关系编程。上图描述的Section1Slotcontentslot和名为ElectronicsHomepageSplashBannerComponent的CMSComponent的包含关系可以体现在如下OCCAPI调用结果中:Spartacus解析上图中的API响应结果,得到name属性如ElectronicsHomepage的SplashBannerComponent的组件知道它的typeCode是SimpleResponsiveBannerComponent,然后在它维护的映射表中,找到CMSComponent对应的AngularComponent的名称是BannerComponent,然后渲染对应的模板文件横幅组件。下图是SAP电商云Spartacus页面首页渲染界面。黄色高亮区域是内容槽Section1Slot的起始位置,两个绿色高亮区域是放置在内容槽中的两个槽。CMSComponent,对应SpartacusUI中以AngularComponent形式呈现的起始位置。虽然从最终用户的角度来说,容器组件的存在是不知道的,但是对于SpartacusUI的标准开发者和需要二次开发的合作伙伴来说,SpartacusUI的容器组件是一个比较重要的概念。SAPSpartacusUI的入口页面,实现代码位于storefront.component.html模板文件中。这个基于Angular的UI界面只有不到30行代码,分为三个主要区域:header、main和footer。在运行时,当客户访问任何一个SpartacusUI时,我们会将渲染后的HTML原生代码对应的DOM元素直接放在上图中第21行的Angular路由指令router-outlet下,成为它的兄弟节点。以客户访问首页的场景为例,最终生成的HTML源码如下:上图是理解SAP电商云SpartacusUI运行时渲染原理的关键,展示了两个重要的容器组件SAP斯巴达克斯。Mark2所示的cx-page-layout,以及它的几个子节点cx-page-slot,分别对应SAPSpartacus的两大容器组件PageLayoutComponent和PageSlotComponent的selector。从PageLayoutComponent容器组件的模板文件实现可以看出,PageLayoutComponent的每个实例实际上都是Angular端Backoffice中CMS管理员维护的一个Page的具体表现形式。当终端用户访问SAP电商云SpartacusUI时,后者调用OCCAPI在BackofficeCMS中获取对应Page的模型数据。Page分配的contentslot信息存储在上图变量第16行的slots$中。PageLayoutComponent使用Angular结构化指令*ngFor,遍历slots$变量,将每个contentslot中记录的数据传递给另一个容器组件PageSlotComponent,其selector为cx-page-slot.PageSlotComponent如第15行所示根据contentslot信息由PageLayoutComponent传入,解析出slot分配的CMSComponents信息。因为单个contentslot可以分配多个CMSComponent,所以在第10行也使用结构指令*ngFor遍历contentslot中需要显示的每个CMScomponent的信息,并将这些信息传递给第19行。我们的团队定义Angular命令cxComponentWrapper。这个以我们部门名称cx-CustomerExperience为前缀的自定义命令会根据传入的CMSComponent类型解析出对应的AngularComponent元数据,然后调用AngularComponent创建API动态创建Component实例并触发渲染流程。采用这种CMS驱动的设计思路,通过PayLayoutComponent和PageSlotComponent的配合,无论CMS管理员对Backoffice中Page要显示的内容进行怎样的修改,SpartacusUI上的代码都能自动响应这些修改,使得以相同的方式响应所有变化。本文概述了SAPWebClientUI、SAPCloudforCustomer和SAPCommerceCloudSpartacusUI中容器组件的设计和操作。我个人认为,学习SAP产品的UI开发,只要掌握其常用的UI组件(参考我的文章:浅谈SAP产品UI开发中组件的概念)和容器的概念及开发方法即可组件,足以胜任大多数场合的工作需要。后续Jerry会分享更多SAPUI开发技术,敬请期待。阅读更多SAPUI和SalesforceUI开发浅谈SAP产品的UI增强思路,体现在SAPCommerceCloud(电商云)UI增强的实现响应式编程是SAP标准产品UI开发中的实践浅谈SAP产品UI开发中组件的概念浅谈SAP产品UISEO的搜索引擎优化-SearchEngineOptimization浅谈SAP产品UI上的消息展示机制Jerry更多原创文章,尽在:《汪子熙》:
