我们知道面向个人用户(to Customer, 简称 2C)软件和面向企业级用户(to Business, 简称 2B)的软件,在设计和实现上都存在一些区别,比如个人软件通常注重直观的用户界面和简单易用的设计,其中用户体验是关键,因为个人软件的目标是满足个人用户的需求和偏好。想想我们每天都在刷的抖音和头条,当然也包括掘金这种软件。
而 2B 企业软件更注重效率和工作流程的优化。其界面可能相对较为复杂,设计目标是提高员工的生产力。同时,企业软件更注重满足企业流程的特定需求,可能具有高度定制的功能,即产品标准里所谓的 Extensibility.
我目前工作在一个使用 Angular 开发的电商 Storefront 开源项目上,项目的 Github 地址如下,项目代号为 Spartacus.
下图是这个 Storefront 编译并使用 ng serve
启动后,看到默认的 homepage.
既然是面向企业的 Angular 应用,就必然存在着定制化需求,比如很难想象电商用户使用 Spartacus 开发出 Storefront 之后,期望这个 Storefront 的外观都千篇一律。
本文通过一个实际的例子来讲解。
同其他 Angular 应用一样,Spartacus Storefront UI 的最小粒度是 Angular Component. 在 Angular 中,Component(组件)是构建用户界面的基本构建块之一。它是一个自包含的、可复用的代码单元,负责控制视图的一部分。Angular 应用的架构是基于组件的,通过组件化开发,可以更好地组织和维护代码。
Angular 组件的核心概念包括:
- 模板(Template): 模板定义了组件的视图,使用 Angular 的模板语法来描述如何渲染和显示数据。模板中可以包含HTML、Angular Directive(指令)和数据绑定。
- 类(Class): 组件的类包含了与模板相关的业务逻辑。这里定义了属性和方法,用于处理用户输入、管理组件状态等。
- 装饰器(Decorator): 装饰器是一个特殊的类型,用于将类标记为 Angular 组件。
@Component
装饰器用于告诉 Angular 如何处理这个类。 - 元数据(Metadata): 装饰器中的元数据提供了关于组件的信息,如选择器(selector)、模板和样式文件的路径等。
可以说只要找准 Angular Component,就把握住了 Angular 应用 Extensibility 实现的命脉。
基于 Angular Component 替换的 Extensibility 思路,即根据要扩展的 UI,找到原本实现这个 UI 界面的 Angular Component,将其替换成客户自开发的 Customer Component,然后把自开发逻辑,实现在这个自开发 Component 里即可。
下面看一个实战案例。
假设我想对下图高亮区域, 即 Storefront 购物车(Cart)页面的产品列表部分,进行二次开发。
在 Chrome 开发者工具里,找到上图实现页面的 Angular 组件对应的 selector:cx-cart-details.
根据找到的 selector cx-cart-details , 作为关键字,在 partacus 源代码里进行搜索。
每个 Angular Component 同其 selector 具有一一对应关系,因此我们找到了 Component selector cx-cart-details, 也就找到了组件名称:CartDetailsComponent:
在 Spartacus 的默认实现里,Commerce Cloud 后台的 Cart 模型 CartComponent,映射的 Angular Component,正好是我们之前找到的 CartDetailsComponent:
所以接下来,我们要做的事情:
- 创建一个新的 Angular Component,扩展自标准 Angular Component CartDetailsComponent.
如下图所示,我给这个新建的 Component 取名为 MyCartComponent,其 selector 为 app-my-cart.
- 新建的 MyCartComponent 扩展自标准的 CartDetailsComponent,既可重用后者已有的业务逻辑,也可以编写新的业务逻辑。
而 UI 界面的二次开发,在该 Component 对应的模板文件,my-cart.component.html 里实现。
为简单起见,在我自定义的 MyCartComponent 里,我仅仅打印出添加到购物车里的产品名称,然后首尾加上两个一级标题。
MyCartComponent 开发完毕后,将其映射到 Commerce Cloud 后台 CMS 模型 CartComponent 上。
下图第83行~89行的语义是,通过 ConfigModule.withConfig 方法,定义了一个优先级比 Spartacus 标准配置优先级更高的客户配置,该配置的内容是一条映射记录,告诉 Spartacus 框架:当页面要渲染 Commerce Cloud 名为 CartComponent 的模型时,请使用我开发的 MyCartComponent 进行页面绘制。
上图第 90 行的代码,用到了 ConfigModule.withConfig
方法。
在 Spartacus 中,ConfigModule.withConfig
是一个非常重要的方法,它可以用于提供应用程序配置。这个方法接收一个配置对象,该对象定义了应用程序的各种设定,例如:路由设定、功能设定或其它特性设定等。这个方法会将这个配置对象合并到应用程序的总配置中。
这个二次开发最后的效果如下:
在生成的 HTML 源代码里,我们自定义的 Angular Component 的 selector app-my-cart, 取代了 Spartacus 标准 Cart Component的 selector cx-cart-details.
以上就是基于 Angular Component 替换的 Extensibility 支持的一个实际案例。
笔者后续会在社区分享更多企业级 Angular 应用 Extensibility 的实现方式。