首页 > 其他分享 >Skeleton Design 理念在 Angular 应用开发中的具体应用一例

Skeleton Design 理念在 Angular 应用开发中的具体应用一例

时间:2023-12-02 16:01:38浏览次数:32  
标签:Observable pagination startWith 用户 Design Angular Skeleton

Skeleton Design 这个概念,想必前端开发人员比较熟悉,而普通的 App 用户,可能甚至都没有听说过,但实际上我们每个人,每天几乎都会受益于这个设计理念。

Skeleton Design 在一些国内技术社区的技术博客里,通常被称为骨架屏设计,是一种用户界面设计策略。骨架屏设计不是一种具体的基于某种编程语言的技术,而是一种设计理念,旨在改善用户体验。通用的骨架屏设计,在页面内容完全加载前,会显示一个包含页面主要布局和元素位置的空白版本。这种方式能够让用户在等待页面加载的过程中,有一个直观的感知,知道接下来会出现什么内容,减少用户的等待焦虑感。

我目前工作在一个使用 Angular 开发的电商 Storefront 开源项目上,项目的 Github 地址如下,项目代号为 Spartacus.

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

在这些 Cost Center 的数据从后台取回来之前,页面显示是这样的:

大家注意到上图一行行灰色的横条吗?这就是一种典型的 Skeleton Design 理念在 Angular 应用里的实现。这种灰色的横条显示,主要目标就是提供一个视觉提示,让用户知道他们可以期待什么类型的信息。

如上图所示,骨架屏通常使用灰色调的占位符来表示正在加载的元素,这种设计方式提供了一种平滑的用户体验,使用户觉得网页的加载更快,更流畅。

试想一下,在用户网络接入速度比较慢,或者后端 API 响应速度比较慢的情况下,如果没有 Skeleton Design 这种设计,那么用户需要在页面加载完成后才能看到完整的内容。特别是在笔者负责开发的 Spartacus 这种电商应用领域内,超过3秒的页面等待就很可能会导致用户的不耐烦,甚至导致他们关闭网站。通过使用骨架屏设计,开发者可以立即显示一个页面的概要,把用户在等待时的注意力分散开,从而提高用户的参与度和用户体验。

本文余下部分,介绍 Spartacus 骨架屏设计的详细技术实现。

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

  /**
   * The ghost data contains an empty list of objects that is used in the UI
   * to render the HTML elements.
   *
   * This list contains 10 items, so that the ghost will show 10 rows by default.
   */
  protected ghostData = { values: new Array(10) } as EntitiesModel<T>;

在 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的空数组。

  /**
   * Loads the data by delegating to the `load` method, which must be implemented
   * in specific implementations of this abstract class.
   *
   * The load method is streamed from the `pagination$` stream, which is initialized
   * with default pagination and structure drive properties.
   */
  getData(...args: any): Observable<EntitiesModel<T> | undefined> {
    return this.pagination$.pipe(
      // we merge any configured pagination from the table structure
      switchMap((pagination) =>
        this.getStructure().pipe(
          map((config) => ({ ...pagination, ...config.options?.pagination }))
        )
      ),
      switchMap((pagination) => this.load(pagination, ...args)),
      startWith(this.ghostData)
    );
  }

startWith 是一个非常有用的 RxJS 操作符,它的主要作用是在 Observable 序列开始之前插入一个指定的元素。这意味着,当你订阅一个 Observable 时,startWith 操作符会立即发出它的参数,然后继续发出 Observable 的值。

例如,我们有一个 Observable,它将发出一个数字序列:

const numbers$ = of(1, 2, 3, 4, 5);

我们可以使用 startWith 操作符在这个数字序列开始前插入一个数字 0:

const numbersWithZero$ = numbers$.pipe(startWith(0));

现在,当我们订阅 numbersWithZero$ 时,它会首先发出 0,然后发出 1, 2, 3, 4, 5。

这种功能在很多情况下都非常有用。例如,在 Angular 中,我们可能会用到 HttpClient 服务来从服务器获取数据。这个过程是异步的,所以我们会使用 RxJS 来处理它。但在数据到达之前,我们可能想要显示一些默认的数据或者加载指示器。这时,startWith 就能派上用场。

// 从服务器获取用户数据,但在数据到达之前,显示一个空的用户对象
const user$ = this.http.get<User>('api/users/1').pipe(
  startWith({id: null, name: 'Loading...'})
);

在这个例子中,user$ 是一个 Observable,它将发出从服务器获取的用户数据。但在数据到达之前,它会先发出一个包含 id: nullname: 'Loading...' 的对象。这样,我们就可以立即更新界面,显示一个加载指示器,然后当真实的数据到达时,再更新为真实的数据。

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

总结

本文首先介绍了 Skeleton Design 设计理念的引入初衷和旨在解决的用户体验,接着以 Spartacus Storefront B2B 页面为例,介绍了 Angular 应用里采用 Skeleton Design 改善页面加载用户体验的例子,希望对 Angular 同行有参考作用。

标签:Observable,pagination,startWith,用户,Design,Angular,Skeleton
From: https://www.cnblogs.com/sap-jerry/p/17871722.html

相关文章

  • Angular Component 内 set 关键字的使用
    "set"关键字在Angular组件的TypeScript代码中通常用于创建和定义类的属性的setter方法。它是一种特殊的方法,负责设置类的私有成员变量的值。通过使用"set"关键字,我们可以在设置属性值时执行一些额外的逻辑,如输入验证、触发事件等。让我们通过一个简单的例子来说明"set"关键字的......
  • Angular Renderer2 的作用和使用场景介绍
    下图将cssclasscx-icon添加到hostdom上。最后效果如下:使用的renderer来自:import{Component,ElementRef,HostBinding,Input,Renderer2,}from'@angular/core';Angular的Renderer2是Angular框架中用于操作DOM元素的重要工具之一。Renderer2的主要......
  • Angular Input 注解在 Spartacus 项目开发中的实际应用场景一例
    @Input()装饰器是Angular中用于在组件中接收父组件传递的数据的一种方式。它的作用是将一个属性标记为输入属性,使得父组件可以将数据绑定到子组件的这些属性上。这样,父子组件之间就可以实现双向数据传递,实现更灵活的组件通信。下面是一个实际的例子:SearchBoxComponent是父组......
  • 使用Angular创建组件,并发布到npm上
    1.组件准备工作1.先新建一个组件库项目ngnewangular-npm-demo2.新建一个存放组件库的目录ngglibrarydemo--prefix=demo;3.进入projects/demo/src/lib目录下新建一个组件,我的组件名叫做list-pagenggclist-page其中对list-page组件的内容进行变更表示是自己......
  • Ant-Design modal对话框未打开时,无法通过uesRef获取modal内部元素DOM节点
    为什么要记录下来呢?因为我在网上和chatGpt上没有搜到合适的解决方案。在CDNS上看到个和我遇到问题一样的,居然要收费才能看,所以自己记下来。当然肯定还有其他的好方案,欢迎大家留言。需求:使用antdV/g6画关系图,类似于企查查上面的那样:点击按钮打开Modal框,把数据渲染到Modal框的div......
  • Angular velocity formulas
    Thisangularvelocitycalculatorusestwodifferentangularvelocityformulasdependingonyourinputparameters.Thefirstangularvelocityequationisanalogoustotheequationforlinearvelocity:The**firstangularvelocity**equationisanalogous......
  • Angular - 生命周期钩子
    Angular会按以下顺序执行钩子方法。可以用它来执行以下类型的操作。钩子方法用途时机ngOnChanges()当Angular设置或重新设置数据绑定的输入属性时响应。该方法接受当前和上一属性值的 SimpleChanges 对象注意,这发生的非常频繁,所以你在这里执行的任何操作都会显著影......
  • 我们开源了一个 Ant Design 的单元测试工具库
    我们是袋鼠云数栈UED团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。本文作者:佳岚欢迎大家点一个小小的Star......
  • Vue3 + [email protected] + UploadPictureCard
    <template><a-uploadname="file"v-model:file-list="showFileList"list-type="picture-card":multiple="multiple":max-count="maxCount":before-up......
  • 通过项目中的实际例子,介绍 LocalStorage 在 Angular 开发中的使用场景
    笔者之前在掘金社区的技术文章,介绍过自己项目组中负责开发的一款基于Angular的电商SDK:Angular应用支持PWA(ProgressiveWebApplication)特性的开发步骤分享Angular应用的搜索引擎优化(SEO)实战指南本文笔者会分享自己项目过程中,在设计这款SDK时使用Web开发领域的......