介绍一个能开发简单SAP UI5应用的在线IDE:StackBlitz

这是Jerry 2021年的第 14 篇文章,也是汪子熙公众号总共第 285 篇原创文章。

在本篇文章之前,Jerry 印象最深的幽灵,应该要算《星际争霸I》里人族能够隐形的空中单位 Wraith( 幽灵战机 ),以及能施放核弹的 Ghost( 幽灵特工).

上周 Jerry 做 SAP Spartacus 开发时,接触到一个新的和幽灵相关的术语:

Skeleton Design(Ghost Design)

读了帮助文档后,发现该名词对我来说只不过是旧瓶装新酒罢了。

本文目录

  • SAP UI5 Busy Dialog
  • 使用代理模式( Proxy Pattern ) 提高 SAP UI5 大尺寸图片的加载体验
  • SAP Spartacus Spinner 控件
  • SAP Spartacus 幽灵设计

我对应用软件的 User Experience 即用户体验领域知之甚少。在 SAP 内部,有专门的用户体验设计师负责这个领域,因此我也不清楚 Skeleton / Ghost Design 准确的中文翻译是啥,姑且就直译成“幽灵设计”吧。

在我看来,无论是幽灵设计,还是之前 SAP UI5 提供的页面加载动画效果,都是改善用户使用体验的一种手段:提示用户当前页面正在加载后台数据,或是执行一些比较费时的操作。

SAP UI5 Busy Dialog

Jerry 从2014年开始使用 SAP UI5 进行 Fiori 开发,经历了 Fiori 1.0 到 2.0 的版本迭代。还记得处理的第一个 CRM Fiori 应用 My Opportunities 的 bug,症状就是修改了 Opportunity 数据之后,用户可以短时间内快速点击下图的 Save 按钮,从而产生多个到 CRM 后台的 OData 保存请求。

当时我的修复该问题的策略就是,在 Save 按钮点击之后,设置一个 Busy Dialog,让其锁住整个页面。这样,用户没有机会再点击 UI 进行任何操作了。直至 OData 请求在后台成功完成,或者收到错误提示,再关闭该 Busy Dialog,页面就能重新恢复可点击状态。

在 Fiori 1.0 时代,Busy Dialog 的外观是一个由5朵花瓣组成的花朵,具有不断旋转的动画效果。

可以通过这个视频查看运行时效果:

https://v.qq.com/x/page/y3225…

Jerry 曾经写过一篇 SAP 社区博客: Fiori Busy Dialog – when is it opened and closed

该文章介绍了 SAP UI5 Busy Dialog 在 Fiori 应用中的使用场景。

一个典型的例子是,用户点击 Fiori Launchpad tile,跳转到某个具体的 Fiori 应用时,浏览器地址栏里的 url 发生变化, sap.ui.controller.doHashChange 会调用 BusyDialog.open 方法,绘制一个花瓣的动画效果:

如 Jerry 之前的文章 深入学习SAP UI5框架代码系列之二:UI5 控件的渲染器 所述,这个花瓣效果的实现 位于其渲染器 LoadingDialogRenderer 的方法 renderFioriFlower 内:

5片花瓣的视觉效果,通过5个 div 元素实现:

而花瓣旋转的动画效果,通过 div 元素 css 类的 animation 系列属性实现:

到了 Fiori 3.0 ,Jerry 发现 Busy Dialog 的外观,已经变成了三个大小不断变化的圆圈。

使用代理模式( Proxy Pattern ) 提高 SAP UI5 大尺寸图片的加载体验

我在 2015 年担任 一个德国 Fiori 客户上线的 Dev Angel 时,该客户有一个自开发需求:其产品主数据的配图动辄超过 10 MB,客户希望浏览器在成功加载这些尺寸巨大的图片之前,显示一些加载动画效果。待到图片完全加载结束时,再关闭加载动画,显示实际图片。

先看没有经过任何优化处理的情况下,如何在 SAP UI5 里使用 Image 控件显示一个 url 指向的图片:第10行调用 SAP UI5 控件 Image 实例的 setSrc 方法,加载 BIG_IMAGE 变量指向的图片。

再看我给客户推荐的基于图片代理的解决方案。

这是运行时的效果:

https://v.qq.com/x/page/n3225…

这个方案实现源代码如下:

上图代码按照运行时执行的先后顺序,有4个关键点,分别用序号1~4表示:

  1. 第10行代码,创建一个新的 Image 实例,充当图片代理的角色。
  2. 第15行代码,UI5 应用里原始的 Image 实例,调用 setSrc 方法,传入的不是实际的大图片地址,而是一个存储在本地的,表示图片正在加载的 gif 文件( 客户自己准备,一个该企业 Logo 旋转的动画效果). 这样,用户打开页面时,首先映入眼帘的,是该本地 gif 文件 loading.gif 实现的不断旋转的动画效果。
  3. 第16行代码,将待加载大尺寸图片的 url 通过输入参数,传递给代理 Image 控件的 setSrc 方法。这会触发浏览器发起对大尺寸图片的加载。
  4. 第13行代码,当代理 Image 控件触发的大尺寸图片加载完成后,触发其 load 回调函数。该回调函数触发,说明大尺寸图片的数据已经完全加载到本地,此时在回调函数里,将大尺寸图片的 url 设置给原始 Image 控件的 src 属性,即可将该图片显示出来。

SAP Spartacus Spinner 控件

Spartacus 里的 Spinner 控件作用类似 SAP UI5 Busy Dialog,下面是一个例子:当第九行代码的组件属性 supportedDeliveryModes$.length 可用时,说明当前订单支持的商品递货模式的相关配置信息,已经从后台取到前台了,此时显示递货模式的选择页面;否则,则显示 ID 为 loading 标识的模板页面,里面只包含一个 Spinner 控件:

这个 Spinner 控件的外观及实现细节,请参考 Jerry 的视频:

https://v.qq.com/x/page/w3160…

最后来说说 SAP Spartacus 的幽灵设计。

Spartacus B2B 功能模块里,正常的 Cost Centers 列表显示如下:

在这些 Cost Center 的数据从后台取回来之前,页面显示如下,这种设计在 SAP Spartacus的帮助文档里,被称为 Skeleton 或者 Ghost Design:

这些在真实数据尚未从后台加载完毕之前,以“占位符”的方式显示在前台的灰色矩形条,绑定在 Angular Component 里的数据,就称为幽灵数据( Ghost Data ).

从Spartacus list.service.ts 的实现源代码能看出,幽灵数据就是一个 length 属性值为10的空数组。

在 Chrome 开发者工具里,能观察到这些幽灵数据具有对应的 CSS class,这使得它们具有灰色矩形的视觉外观:

Cost Center 表格显示的数据最终通过 list.service.ts 从 SAP Commerce Cloud 后台取出,取数逻辑通过 Angular 响应式编程库 RxJS的 pipe 方法驱动:第101行 switchMap 操作符里的箭头函数,输入参数 pagination 包含了去 Commerce Cloud 取数据使用的分页设置,函数体 this.load 发送 HTTP 请求,消费 Commerce Cloud 的 OCC API. 而第102行的 startWith操作符,语义上相当于给 pipe 驱动的 Observable 流赋上一个初始值,该初始值即为 length 属性为10的空数组。

这样,从运行时序来说,任何消费 getData 函数返回的 Observable 对象的 Angular UI 组件,都会先显示 startWith 设置的初始值,即幽灵数据。待从 Commerce Cloud 后台加载的真实数据返回给浏览器之后,组件自动刷新并显示这些真实的业务数据。

本文介绍了 Jerry 工作过的 SAP 产品里,当用户操作 UI 触发了某些后台数据加载时,为了提升用户体验而引入的一些页面效果的技术实现,希望对大家有所帮助,感谢阅读。

更多阅读

更多Jerry的原创文章,尽在:”汪子熙”: