PrimeNG 下个阶段的 UI 开发(二)
原文:
zh.annas-archive.org/md5/08636559d2a183d1de1e803d10540e28译者:飞龙
第六章:与表、列表和卡片组件一起工作
随着我们继续使用 PrimeNG 和 Angular 的旅程,我们发现自己处于数据展示组件的领域。在本章中,我们将重点关注三个关键组件:数据表、列表和卡片组件。这些组件是任何应用程序的功臣,负责以清晰、简洁和用户友好的方式向用户展示数据。它们是我们应用程序中的原始数据与用户交互的精致、交互式界面之间的桥梁。
本章的目标是向您提供必要的知识和技能,以便您能够有效地利用数据表、列表和卡片组件,以最用户友好的方式呈现数据。通过掌握这些组件,您可以确保用户能够轻松理解并交互数据,最终提高用户参与度和满意度。
在本章中,我们将涵盖以下主题:
-
使用 PrimeFlex 创建响应式布局
-
介绍数据展示组件
-
与数据表组件一起工作
-
与列表组件一起工作
-
与卡片组件一起工作
技术要求
本章包含 PrimeNG 展示组件的各种代码示例。您可以在以下 GitHub 仓库的chapter-06文件夹中找到相关源代码:github.com/PacktPublishing/Next-Level-UI-Development-with-PrimeNG/tree/main/apps/chapter-06。
使用 PrimeFlex 创建响应式布局
Flexbox和Grid等。
将 PrimeFlex 与 PrimeNG 集成
PrimeFlex 可以通过npm安装轻松集成到 PrimeNG 中:
npm install primeflex
在安装过程之后,我们将 PrimeFlex 库包含到我们的styles.scss文件中:
// styles.scss
@import 'primeflex/primeflex.scss';
一旦我们导入primeflex.scss,我们就能创建一个 Angular 应用程序,确保适当的间距、排版、布局以及所有其他基本元素。
让我们比较一下使用和未使用 PrimeFlex 构建布局的方式。
在没有实用库如 PrimeFlex 的情况下构建布局可能会很繁琐。您可能会发现自己正在编写重复且冗长的 CSS 代码,如下面的代码示例所示:
<h1 [routerLink]="['/']">Welcome to chapter-06</h1>
<div class="layout-wrapper">
<aside>
<nav>
<p-menu [model]="items" />
</nav>
</aside>
<main>
<router-outlet />
</main>
</div>
....
styles: [
`
.layout-wrapper {
display: flex;
gap: 4rem;
flex-wrap: wrap;
}
`,
],
我们通过创建.layout-wrapper类并向其中添加 CSS 语法来应用样式。这是一个由网络浏览器支持的标准化 CSS 实现。使用常规 CSS,您需要从头开始编写自己的样式。
另一方面,PrimeFlex 通过提供封装常见 CSS 属性的实用类来简化这一过程。让我们看看带有 PrimeFlex 实用类的模板:
<h1 [routerLink]="['/']">Welcome to chapter-06</h1>
<div class="flex flex-wrap gap-7">
...
</div>
通过使用常见的 CSS 实用类,我们可以简化我们的模板,例如将.layout-wrapper类转换为flex flex-wrap gap-7,从而消除编写自定义 CSS 代码的需求。
PrimeFlex 实用类的使用为你的整个 Angular 应用提供了易用性和一致性,尽管正常的 CSS 提供了更大的灵活性和定制选项,但需要更多的努力和专业知识来实现所需的样式。让我们在浏览器中查看:
图 6.1 – PrimeFlex 类示例
你可以观察到实用类映射到它们各自的 CSS 样式,例如,从 flex 到 display: flex !important;。
这里有一些与布局(Flexbox 和 Grid)和文本相关的实用类示例:
图 6.2 – 常见 PrimeFlex 实用类
这些类是 PrimeFlex 对 CSS 的实用优先方法的一部分,为你提供了一组可重用的类,这些类封装了常见的布局和文本样式模式。通过使用这些类,你可以快速构建复杂的布局并应用文本样式,而无需编写自定义 CSS 代码,从而实现更高效和可维护的开发过程。有关完整实用类集,请查阅 primeflex.org 的文档。
在 PrimeFlex 中使用 Flexbox
PrimeFlex 提供了一个强大且多功能的 Flexbox 实用系统,允许你创建灵活和响应式的布局。使用 Flexbox,你可以轻松地在容器内分配和排列元素,使其成为构建现代和动态用户界面的优秀工具。
创建弹性容器
要创建 Flexbox 布局,你需要指定一个容器元素作为弹性容器。通过将 flex 类应用于容器,你可以启用 Flexbox 行为,允许子元素成为弹性项:
<div class="flex">
<div class="text-center p-3 bg-primary">Flex Item 1</div>
<div class="text-center p-3 bg-primary">Flex Item 2</div>
<div class="text-center p-3 bg-primary">Flex Item 3</div>
</div>
在前面的代码示例中,flex 类被应用于容器元素,这使得它成为一个弹性容器。容器内的子元素自动成为弹性项。
这是 图 6*.3* 的基本代码,你将在后面看到。
应用弹性方向
Flexbox 还提供了四种主要方向来在弹性容器内排列弹性项:row、row-reverse、column 和 column-reverse。方向是通过将以下类之一应用于弹性容器来确定的:
-
flex-row: 项目从左到右以行形式排列 -
flex-row-reverse: 项目从右到左以行形式排列 -
flex-column: 项目从上到下以列的形式排列 -
flex-column-reverse: 项目从下到上以列的形式排列
这是一个我们如何创建具有不同布局的弹性容器的示例:
图 6.3 – PrimeFlex Flexbox 示例
在这个示例中,我们通过轻松地应用不同的类,在行或列中创建多样化的布局,从而利用 Flexbox 的力量。
注意
要了解更多关于 Flexbox 及如何调试的信息,您可以访问 developer.chrome.com/docs/devtools/css/flexbox/。这是一个有用的资源,它提供了关于理解 Flexbox 和解决您可能遇到的问题的见解和指导。
使用 flex wrap
默认情况下,弹性项目会尝试适应单行。然而,如果空间不足,弹性项目会缩小以适应。要控制弹性项目的换行行为,可以使用以下类:
-
flex-wrap: 如果需要,项目将换行到多行 -
flex-wrap-reverse: 如果需要,项目将按相反顺序换行到多行 -
flex-nowrap: 项目保持在单行上
让我们将换行功能应用到我们的弹性容器中:
<div class="flex flex-wrap">
...
</div>
在此示例中,弹性容器应用了 flex-wrap 类,允许弹性项目在需要时换行。
使用 justify content
Flexbox 提供了强大的对齐选项,用于在主轴和交叉轴上定位弹性项目。PrimeFlex 提供了各种类来控制对齐:
-
justify-content-end: 这会将弹性项目沿主轴对齐到弹性容器的末尾 -
justify-content-center: 这会将弹性项目沿弹性容器的主轴居中 -
justify-content-between: 这将在主轴上均匀分布弹性项目,并在它们之间留有相等的空间 -
justify-content-around: 这将在主轴上均匀分布弹性项目,并在它们周围留有相等的空间 -
justify-content-evenly: 这将在主轴上均匀分布弹性项目,并在它们之间留有相等的空间,包括第一个项目之前和最后一个项目之后
这些对齐类可以应用于弹性容器或单个弹性项目:
<div class="flex flex-wrap justify-content-evenly">
...
</div>
在此先前的示例中,弹性容器应用了 justify-content-evenly 类,它将弹性项目均匀分布,并在它们周围留有相等的空间。flex-wrap 类允许项目在需要时换行。
考虑到所有的 Flexbox 代码,让我们看看结果:
图 6.4 – Flexbox 示例
您可以看到元素是一个弹性容器,如果需要,弹性项目会换行。弹性项目沿主轴均匀分布,它们之间以及容器的开始和结束处都有相等的空间。
使用 PrimeFlex 中的网格系统
PrimeFlex 中的网格系统是构建复杂布局的另一个强大功能,它提供了简单直观的语法来构建网格和排列页面上的元素。
PrimeFlex 网格遵循 12 列结构。每一行由一个容器组成,该容器包含一个或多个列。行内的列会根据可用空间自动调整其宽度。
要创建一个网格布局,您需要将内容包裹在一个带有 grid 类的容器元素中。在容器内部,您可以使用 col 类来定义列。列是通过添加 col-{size} 类来指定的,其中 {size} 代表元素应跨越的列数。
这里是一个具有两列的基本网格结构的示例:
<div class="grid">
<div class="col-6">
<div class="text-center p-3 bg-primary">6</div>
</div>
<div class="col-6">
<div class="text-center p-3 bg-primary">6</div>
</div>
<div class="col-6">
<div class="text-center p-3 bg-primary">6</div>
</div>
<div class="col-6">
<div class="text-center p-3 bg-primary">6</div>
</div>
</div>
在这个示例中,我们有一个包含两列的网格容器。每个列跨越六列,从而形成两个等宽的列。以下是结果:
图 6.5 – PrimeFlex 网格示例
PrimeFlex 网格还提供了响应式类,允许您为不同的屏幕尺寸创建不同的布局。您可以使用以下语法根据屏幕断点指定不同的列大小:
-
sm:小屏幕(576px 及以上) -
md:中等屏幕(768px 及以上) -
lg:大屏幕(992px 及以上) -
xl:超大屏幕(1200px 及以上)
让我们使用断点来创建响应式布局:
<div class="grid">
<div class="col-12 md:col-6 lg:col-3">
<div class="text-center p-3 bg-primary">6</div>
</div>
...
</div>
在这个示例中,我们有一个包含两列的网格容器。默认情况下,在小型屏幕上(12 列),每个列宽度为全宽,在中等屏幕上(六列)宽度为半宽,在大屏幕上(四列)宽度为三分之一。
PrimeFlex 是一个对网页开发者非常有价值的工具,它提供了一种简化的 CSS 样式方法。它与 PrimeNG 的集成增强了开发体验,提供了一致且灵活的设计系统。在下一节中,我们将介绍 PrimeNG 数据显示组件。
介绍数据显示组件
正如我们所知,数据是任何应用程序的生命线,但原始数据本身并不很有用。真正重要的是我们如何向用户展示这些数据。这正是数据显示组件发挥作用的地方。它们是将原始数据转换为有意义信息的工具,为用户提供洞察力,并使他们能够与数据互动。
PrimeNG 提供了各种数据显示组件。这些组件旨在以清晰、简洁和用户友好的方式展示数据。它们包括数据表、列表、卡片等等。每个组件都有其优势和用例,共同提供了一个全面的数据显示工具包。没有这些组件,用户将面临难以解释和分析的原始数据。这可能导致错误、误解和不良决策。
让我们看看以下 PrimeNG 数据显示组件及其使用场景:
-
数据表,例如,非常适合以结构化格式显示大量数据。它们支持排序、过滤和分页等功能,使用户能够轻松导航和与数据互动。
-
另一方面,列表非常适合以简单直接的方式显示一系列项目。它们非常灵活,可以用于各种用例,从简单的文本项列表到具有自定义布局的复杂列表。
-
卡片是数据展示的另一个强大工具。它们以灵活和可扩展的格式展示相关信息的集合,是一种很好的展示方式。卡片可以包含任何类型的内容,从文本和图像到按钮和链接,并且可以以各种方式排列,以创建视觉上吸引人的布局。
在接下来的章节中,我们将更深入地探讨这些组件,探讨如何在您的 Angular 应用程序中使用它们。我们将提供代码示例来说明它们的用法,并讨论每个组件可用的各种选项和配置。
注意
记住,有效数据展示的关键不仅在于选择正确的组件,还在于正确地使用它们。这关乎理解数据,知道哪些信息对用户来说很重要,并以易于理解和交互的方式呈现。
与数据表格组件一起工作
深入数据展示的世界,我们发现周围环绕着众多组件,每个组件都有其独特的特性和功能。在这些组件中,PrimeNG 表格因其多功能性和强大的功能而脱颖而出,可以将原始数据转换为有意义的、交互式的和视觉上吸引人的信息。
要在您的 Angular 项目中使用 PrimeNG 表格,您首先需要从 PrimeNG 中导入 TableModule。您可以通过将以下 import 语句添加到您的模块文件中来实现这一点:
import { TableModule } from 'primeng/table'
本节将探讨 PrimeNG 表格的各种功能和特性,为您提供实际示例和见解,帮助您在应用程序中充分利用其全部潜力。在以下示例中,我们将使用示例产品数据。以下是 Product 的界面:
interface Product {
id: number
name: string
price: number
description: string
quantity: number
rating: number
category: string
}
那么,让我们开始学习表格。
创建基本表格
PrimeNG 表格需要一组数据来显示,以及定义如何表示这些数据的列组件。以下是一个简单的示例:
<p-table
[value]="products"
[tableStyle]="{ 'min-width': '50rem' }"
>
<ng-template pTemplate="header">
<tr>
<th>ID</th>
<th>Name</th>
<th>Category</th>
<th>Quantity</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-product>
<tr>
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
<td>{{ product.category }}</td>
<td>{{ product.quantity }}</td>
</tr>
</ng-template>
</p-table>
让我们分解代码片段:
-
<p-table>: 这是 PrimeNG 表格组件,用于显示表格数据。 -
[value]="products": 这个属性绑定将products属性绑定到p-table组件的value属性。这意味着组件代码中的products变量是表格的数据源。 -
[tableStyle]="{ 'min-width': '50rem' }": 这个属性绑定将内联 CSS 样式对象绑定到p-table组件的tableStyle属性。提供的样式对象将表格的最小宽度设置为50rem。 -
<ng-template pTemplate="header">: 这是一个表格表头行的模板。它定义了列标题。在这种情况下,表格有四列:ID、Name、Category和Quantity。 -
<ng-template pTemplate="body" let-product>:这是一个表格主体的模板。它定义了数据每一行应该如何显示。let-product语法用于创建一个局部模板变量 product,它保存了每一行的当前产品对象。 -
在身体模板内部,我们为每一行有一个
<tr>元素,并为每一行中的每个单元格有一个<td>元素。{{ product.id }}、{{ product.name }}、{{ product.category }}和{{ product.quantity }}表达式用于将当前产品对象的属性绑定到单元格中。
之后,我们将有一个基本的表格,如下所示:
图 6.6 – 基本表格
带动态列的表格
可以使用 *ngFor 指令动态定义列。这在您的数据结构事先未知或可以动态变化时特别有用。下面是如何做到这一点的方法:
cols = [
{ field: 'id', header: 'ID' },
{ field: 'name', header: 'Name' },
{ field: 'category', header: 'Category' },
{ field: 'quantity', header: 'Quantity' },
]
...
<p-table
[columns]="cols"
[value]="products"
[tableStyle]="{ 'min-width': '50rem' }"
>
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{ col.header }}
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowData let-columns="columns">
<tr>
<td *ngFor="let col of columns">
{{ rowData[col.field] }}
</td>
</tr>
</ng-template>
</p-table>
在这个例子中,columns 属性绑定到 cols 数组,该数组包含列的定义。每一列都是一个对象,具有 header 属性(列标题)和 field 属性(绑定到数据对象的属性)。由于表格数据是在组件中定义的,因此可以为用户提供选择要显示的列、重新排序列或动态向表格中添加或删除列的选项。
带排序的表格
排序是数据展示的基本方面,允许用户以对特定任务有意义的方式对数据进行排序。PrimeNG 为表格中的数据排序提供了内置功能。
下面是如何在 PrimeNG 表格组件中启用排序的示例:
<p-table [value]="products">
<ng-template pTemplate="header">
<tr>
<th pSortableColumn="name">Name
<p-sortIcon field="name"></p-sortIcon>
</th>
<th pSortableColumn="price">Price
<p-sortIcon field="price"></p-sortIcon>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-product>
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
</tr>
</ng-template>
</p-table>
在这个例子中,使用 pSortableColumn 指令指定当点击列标题时应按哪个字段排序数据。使用 p-sortIcon 组件显示表示排序顺序的图标。
默认情况下,点击列标题一次将按升序排序数据。再次点击它将按降序排序数据。让我们看看结果:
图 6.7 – 带排序的表格
您可以看到,在截图上,点击 价格 标题后,表格按价格升序排序。
带过滤的表格
过滤是另一个强大的功能,允许用户根据特定标准缩小表格中显示的数据。同样,PrimeNG 为此提供了内置功能。
要为列启用过滤,您需要向表格中的列定义添加一些自定义模板。以下是如何做到这一点的示例:
<p-table
[value]="products"
[globalFilterFields]="['name', 'price']"
#dt
>
<ng-template pTemplate="caption">
<div class="flex">
<button pButton label="Clear" class="p-button-outlined"
icon="pi pi-filter-slash" (click)="dt.clear()"
></button>
<span class="p-input-icon-left ml-auto">
<i class="pi pi-search"></i>
<input pInputText type="text" placeholder="Search keyword"
(input)="dt.filterGlobal($event.target.value, 'contains')" />
</span>
</div>
</ng-template>
<ng-template pTemplate="header">
<tr>
<th>
<input pInputText type="text" placeholder="Search by name"
(input)="dt.filter($event.target.value, 'name', 'contains')"
/>
</th>
<th>
<input pInputText type="text" placeholder="Search by price"
(input)="dt.filter($event.target.value, 'price', 'equals')"
/>
</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-product>
<tr>
<td>{{ product.name }}</td>
<td>{{ product.price }}</td>
</tr>
</ng-template>
<ng-template pTemplate="emptymessage">
<tr>
<td colspan="7">No products found.</td>
</tr>
</ng-template>
</p-table>
之前的代码是一个具有列和全局过滤功能的 PrimeNG 表格的示例。让我们分解一下:
-
<p-table>是一个 PrimeNG 表格组件,用于显示表格数据。 -
[value]="products"是一个属性绑定,将products属性绑定到<p-table>组件的value属性上。这意味着组件代码中的products变量是表格的数据源。 -
[globalFilterFields]="['name', 'price']"属性绑定将字段名数组(name和price)绑定到<p-table>组件的globalFilterFields属性上。globalFilterFields属性允许你指定要应用全局过滤器的字段/列。在这种情况下,全局过滤器将应用于表格的name和price字段。 -
#dt是一个名为dt的模板引用变量,它被分配给<p-table>组件。模板引用变量允许你在模板代码中引用组件,并在需要时访问其属性和方法。 -
<ng-template pTemplate="caption">模板包含一个清除所有过滤器的按钮和一个用于全局搜索的输入字段。当按钮被点击时,会调用dt.clear()方法来清除所有过滤器。当用户在全局搜索输入字段中输入时,会调用dt.filterGlobal()方法来根据输入值过滤所有行。 -
<ng-template pTemplate="header">模板包含每个列的输入字段。当用户在这些输入字段中输入时,会调用dt.filter()方法来根据对应列的输入值过滤行。 -
<ng-template pTemplate="body" let-product>模板定义了如何显示每一行数据。let-product语法用于创建一个局部模板变量product,它为每一行持有当前的产品对象。 -
当没有行可供显示时,会显示
<ng-template pTemplate="emptymessage">模板,这可能是因为products数组为空,或者没有行匹配当前的过滤器。
让我们看看最终的结果:
图 6.8 – 带过滤的表格
例如,用户可以通过在列标题或全局搜索输入字段中的输入字段中输入来过滤行。用户还可以通过点击 清除 按钮来清除所有过滤器。
带有分页器的表格
当处理大量数据集时,一次性显示所有数据可能会让人感到不知所措且不切实际。分页是解决这个问题的常见方法,它允许用户一次查看数据的一个子集。PrimeNG 的表格组件内置了分页器,这使得实现此功能变得非常简单。
要在 PrimeNG 表格中启用分页,你只需将 paginator 属性设置为 true 并定义 rows 属性来指定每页的行数:
<p-table
[value]="products"
[paginator]="true"
[rowsPerPageOptions]="[5,10,20]"
[rows]="10"
>
<!-- Table content -->
</p-table>
让我们逐一查看每个属性及其用途:
-
[value]="products":这会将表格的值绑定到一个名为products的变量上。 -
[paginator]="true":这启用了表格的分页功能。 -
[rowsPerPageOptions]="[5,10,20]": 这定义了每页显示行数的选项。在这种情况下,选项设置为5、10和20。用户可以选择这些选项之一来控制表格中显示的行数。 -
[rows]="10": 这设置了每页显示的行数。在这种情况下,它设置为10。这意味着表格的每一页将显示最多 10 行。
让我们看看启用了分页器功能的表格:
图 6.9 – 带有分页器的表格
此截图展示了选择要显示的行数的选项,默认值设置为10。此外,分页器功能允许在不同页面之间无缝导航。
总结来说,PrimeNG 的表格组件提供了一个强大且灵活的解决方案,用于显示表格数据。具有排序、过滤和分页等功能,为开发者提供了以有组织和交互方式展示数据的工具。
注意
要了解更多关于表格组件以及探索其他功能,例如可伸缩的列、冻结列和可滚动的表格,您可以访问 PrimeNG 文档网站 primeng.org/table。
接下来,我们将探讨网络应用程序中数据展示的另一个重要方面:PrimeNG 的列表组件,它提供了一套多样化的工具,用于显示和与数据列表互动。
与列表组件一起工作
PrimeNG 提供各种列表组件,以满足不同的需求和用例。这些组件旨在将原始数据转换为有意义的列表,为用户提供直观的方式与信息互动。
PrimeNG 的列表组件包括几个关键元素,可用于创建多样化的列表展示:
-
DataView: 此元素提供网格和列表视图来显示数据,并具有排序和过滤选项 -
OrderList: 此元素允许用户在列表中对项目进行重新排序 -
PickList: 此元素允许用户从列表中选择项目并将它们移动到另一个列表
这些组件不仅关乎数据的显示;它们还提供排序、过滤和选择等功能,增强了用户与数据互动的能力。让我们更详细地看看每一个。
DataView
DataView是一个多功能的组件,特别适用于您需要以结构化方式展示大量数据时。它提供了各种功能,如分页、排序和可定制的模板,使其成为构建数据驱动应用程序的绝佳选择。
在以下场景中,您可能需要考虑使用 PrimeNG 的DataView组件:
-
DataView组件可以帮助您高效地实现这一点 -
DataView组件可以用于以网格或列表格式显示结果,并提供分页和排序选项 -
DataView可用于在各个小部件中一致地展示数据,提供连贯的用户体验
在以下子节中,让我们考虑一个示例,其中我们有一个产品集合,我们希望使用DataView组件来显示。每个产品都有名称、类别和价格等属性。我们将以列表布局展示产品,使用户能够浏览它们并将项目添加到购物车中。
创建基本数据视图
在使用DataView组件之前,确保在您的应用程序中安装了 PrimeFlex 非常重要。这是必要的,因为DataView依赖于 PrimeFlex 提供的Grid功能来有效地组织和展示数据。有关安装 PrimeFlex 的详细说明,请参阅本章前面的部分。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { DataViewModule } from 'primeng/dataview'
一旦我们安装并导入了依赖项,我们就可以在我们的 Angular 模板中使用DataView组件。以下是我们如何以列表布局显示产品的示例:
<p-dataView [value]="products">
<ng-template pTemplate="list" let-products>
<div class="col-12" *ngFor="let product of products">
<div class="flex flex-column xl:flex-row xl:align-items-start p-4 gap-4">
<div class="flex flex-column sm:flex-row justify-content-between align-items-center xl:align-items-start flex-1 gap-4">
<div class="flex flex-column align-items-center sm:align-items-start gap-3">
<div class="text-2xl font-bold text-900">{{ product.name }}</div>
<div class="flex align-items-center gap-3">
<span class="flex align-items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ product.category }}</span>
</span>
</div>
</div>
<div class="flex sm:flex-column align-items-center sm:align-items-end gap-3 sm:gap-2">
<span class="text-2xl font-semibold">{{'$'+ product.price }}</span>
<button pButton icon="pi pi-shopping-cart" class="md:align-self-end mb-2 p-button-rounded" ></button>
</div>
</div>
</div>
</div>
</ng-template>
</p-dataView>
以下是代码分解:
-
<p-dataView>:这是 PrimeNG 库中的 Angular 组件,用于在视图中显示数据。 -
[value]="products":此属性绑定将组件代码中的products属性绑定到<p-dataView>组件的value属性。这意味着组件代码中的products变量是数据视图的数据源。 -
<ng-template pTemplate="list" let-products>:此模板渲染数据视图中的每个项目。pTemplate属性值为"list"表示此模板用于列表项。let-products属性声明了一个名为products的局部变量,它代表数据视图中的products数组。
因此,我们创建了一个包含三个项目的产品列表:
图 6.10 – 基本数据视图
带分页的 DataView
如果您有大量产品并希望将它们显示在多个页面上,您可以在DataView组件中启用分页。以下是如何启用具有特定每页行数的分页的示例:
<p-dataView
[value]="products"
[rows]="4"
[paginator]="true"
>
<!-- DataView template -->
</p-dataView>
在这里,我们将rows属性设置为4,表示我们希望每页显示四个产品。通过将paginator属性设置为true,DataView组件自动添加分页控件,使用户能够浏览页面。
带排序的 DataView
DataView组件还提供了内置的排序功能,允许用户根据特定标准对数据进行排序。以下是如何启用排序并添加下拉菜单以选择排序选项的示例:
<p-dataView
[value]="products"
[rows]="4"
[paginator]="true"
[sortField]="sortField"
[sortOrder]="sortOrder"
>
<ng-template pTemplate="header">
<div class="flex flex-column md:flex-row md:justify-content-between">
<p-dropdown
[options]="sortOptions"
[(ngModel)]="sortKey"
placeholder="Sort By Price"
(onChange)="onSortChange($event)"
styleClass="mb-2 md:mb-0"
/>
</div>
</ng-template>
<!-- DataView template -->
</p-dataView>
...
sortOptions = [
{ label: 'Price High to Low', value: '!price' },
{ label: 'Price Low to High', value: 'price' }
];
sortOrder!: number;
sortField!: string;
onSortChange(event: HTMLInputElement) {
const value = event.value;
if (value.indexOf('!') === 0) {
this.sortOrder = -1;
this.sortField = value.substring(1, value.length);
} else {
this.sortOrder = 1;
this.sortField = value;
}
}
让我们分解代码以了解其功能:
-
[value]="products":此绑定将父组件中的products数组绑定到DataView组件,该组件将成为显示项的数据源。 -
[rows]="4": 如果启用了分页,这将设置每页显示的行数。 -
[paginator]="true": 这启用了DataView组件的分页功能。 -
[sortField]="sortField"和[sortOrder]="sortOrder": 这些属性用于控制数据的排序;sortField指定按哪个字段排序数据,而sortOrder指定顺序(升序或降序)。 -
<p-dropdown ... />: 这行代码创建了一个下拉列表,其选项由sortOptions数组定义。当用户选择一个选项时,会调用onSortChange方法。 -
sortOptions: 这个数组定义了下拉列表中可用的排序选项。value字段包含一个表示排序标准的字符串。如果值以!开头,表示降序。 -
onSortChange(event: HTMLInputElement): 当用户从下拉列表中选择排序选项时,会调用此方法。它解析所选值并相应地设置sortOrder和sortField属性。
通过使用这些属性和模板,您可以在 DataView 组件中启用排序,并为用户提供无缝的排序体验。在下面的屏幕截图中,您可以看到我们构建了一个每次显示四个项目的产品列表,并按 价格从低到高 排序:
图 6.11 – 带排序和分页的数据视图
到目前为止,我们已经见证了 PrimeNG 的 DataView 在提供可适应数据展示方面的出色能力。现在,让我们探索 PrimeNG 的 OrderList,这是一个专门组件,为列表管理带来了独特的触感。
排序列表
在与项目集合交互时,有时这些项目的顺序很重要。这就是 PrimeNG 的 OrderList 发挥作用的地方。OrderList 组件是一个强大的工具,它允许您在 Angular 应用程序中管理和排序项目集合。它就像有一个个人助理来帮助您组织数据。
OrderList 在您需要为用户提供手动排序项目列表的方式时特别有用,例如在待办事项列表中优先排序任务、重新排列书籍章节、管理播放列表、分类产品或按相册排序照片。
创建基本排序列表
让我们通过一个示例来深入了解 OrderList 组件如何在应用程序中使用。我们将创建一个用户可以重新排序的产品列表。
OrderList 组件利用 Angular CDK 的 DragDropModule 来处理拖放操作。确保安装了 @angular/cdk 包非常重要。如果没有,我们需要通过以下命令将其添加到我们的 package.json 文件中:
npm install @angular/cdk
注意
@angular/cdk(组件开发工具包或 CDK)库由 Angular 团队提供,提供了一组可重用的组件、指令和实用函数,以简化 Angular 应用程序的开发。CDK 提供了一套工具和构建块,有助于创建一致、可访问和响应式的用户界面。你可以在 material.angular.io/cdk 上了解更多关于 CDK 的信息。
然后,我们还需要从 PrimeNG 中导入 OrderListModule 到我们的组件:
import { OrderListModule } from 'primeng/orderlist'
一旦我们安装并导入了依赖项,我们就可以在我们的 Angular 模板中使用 OrderList 组件。以下是我们如何显示顺序列表中的产品的示例:
<p-orderList
[value]="products"
[listStyle]="{ 'max-height': '30rem' }"
header="Products"
>
<ng-template let-product pTemplate="item">
<div class="flex flex-column xl:flex-row xl:align-items-start gap-4">
<div
class="flex flex-column sm:flex-row justify-content-between align-items-center xl:align-items-start flex-1 gap-4"
>
<div
class="flex flex-column align-items-center sm:align-items-start gap-3"
>
<div class="text-xl font-bold text-700">{{ product.name }}</div>
<div class="flex align-items-center gap-3">
<span class="flex align-items-center gap-2">
<i class="pi pi-tag"></i>
<span class="font-semibold">{{ product.category }}</span>
</span>
</div>
</div>
<div
class="flex sm:flex-column align-items-center sm:align-items-end gap-3 sm:gap-2"
>
<span class="text-xl font-semibold">{{
'$' + product.price
}}</span>
<button
pButton
icon="pi pi-shopping-cart"
class="md:align-self-end mb-2 p-button-rounded"
></button>
</div>
</div>
</div>
</ng-template>
</p-orderList>
下面是示例代码的分解:
-
[value]="products":这将我们的产品列表绑定到OrderList的value属性。 -
header="Products":这用于设置列表的标题。 -
[listStyle]="{ 'max-height': '30rem' }":这设置了列表的最大高度。 -
<ng-template let-product pTemplate="item">:这自定义了列表中每个项目的显示方式。我们可以使用let-product语法访问当前产品。
现在,在下面的屏幕截图中,你会注意到产品列表被标记为Products。此外,你还有能力通过位于左侧面板中的箭头按钮选择产品并在列表中重新定位它:
图 6.12 – 基本顺序列表
带有过滤的 OrderList
OrderList 组件也支持过滤和搜索功能,使用户能够快速在源列表中找到特定的项目。要启用过滤,我们可以使用 filterBy 和 filterPlaceholder 属性:
<p-orderList
[value]="products"
[listStyle]="{ 'max-height': '30rem' }"
header="Products"
filterBy="name"
filterPlaceholder="Filter by name"
>
<!-- Item template here... -->
</p-orderList>
在此示例中,我们将 filterBy 属性设置为 name 以根据产品名称过滤产品,而 filterPlaceholder 属性指定了搜索输入字段的占位符文本。以下是最终结果:
图 6.13 – 带有过滤的顺序列表
如屏幕截图所示,我们可以在搜索框中输入产品名称或产品名称来过滤和搜索产品 22。
带有拖放的 OrderList
OrderList 组件允许用户使用拖放手势重新排序项目。默认情况下,拖放功能是禁用的。要启用它,我们可以使用 [``dragdrop] 属性:
<p-orderList
[value]="products"
[listStyle]="{ 'max-height': '30rem' }"
header="Products"
[dragdrop]="true"
>
<!-- Item template here... -->
</p-orderList>
启用拖放允许用户点击并保持对项目的选择,将其拖动到目标列表中的新位置,然后放下以重新排序项目。此功能为用户提供了一种直观的交互方式,根据他们的偏好重新排列项目。
我们发现了 PrimeNG 的 OrderList 的动态功能,增强了我们应用程序中的列表交互。现在,让我们将注意力转向 PrimeNG 的 PickList,这是一个双列表界面,承诺提供更多的交互性和多功能性。
PickList
PrimeNG 的PickList组件是一个强大的工具,它允许开发者在不同的列表之间重新排序项目时创建交互式和可定制的列表。它提供了一个用户友好的界面,用于以拖放的方式管理和操作数据。无论您需要实现多选功能、构建任务管理系统还是创建自定义表单构建器,PickList组件都提供了灵活性和功能性,以满足您的需求。
在以下场景中这可能是有益的:
-
PickList组件可用于在源列表中显示可用任务列表,并在目标列表中显示分配的任务列表。用户可以根据其分配状态轻松地在列表之间移动任务。 -
PickList组件可以帮助组织表单元素。您可以在源列表中显示所有可用字段,并将选定的字段移动到目标列表中,以定义表单结构。这提供了一种方便的方式,根据用户偏好动态生成表单。 -
PickList组件可以通过允许用户将选定的产品移动到目标列表(代表他们的定制目录)来简化此过程。
通过利用PickList组件,您可以增强用户体验,改进数据组织,并在您的应用程序中实现高效的数据操作。
让我们考虑一个例子,其中我们有一个产品列表,并希望允许用户使用 PrimeNG 的PickList组件将选定的产品添加到他们的购物车中。要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { PickListModule } from 'primeng/picklist'
一旦我们安装并导入了依赖项,我们就可以在我们的 Angular 模板中使用PickList组件。以下是我们如何以选择列表布局显示产品的示例:
<p-pickList
[source]="products"
[target]="selectedProducts"
sourceHeader="Available Products"
targetHeader="Selected Products"
[dragdrop]="true"
[responsive]="true"
[sourceStyle]="{ height: '30rem' }"
[targetStyle]="{ height: '30rem' }"
breakpoint="1400px"
>
<ng-template let-product pTemplate="item">
<!-- Item template here... -->
</ng-template>
</p-pickList>
在此示例中,我们将products和selectedProducts数组分别传递给PickList组件的source和target属性。我们还使用sourceHeader和targetHeader属性为源列表和目标列表提供标签。
让我们看看最终结果:
图 6.14 – 示例选择列表
当您运行应用程序时,您应该看到两个列表并排渲染。左侧列表表示可用产品,右侧列表表示选定的产品。用户可以通过使用PickList组件提供的拖放功能从源列表中选择产品并将它们移动到目标列表。
总结来说,PrimeNG 的列表组件是一套强大的工具,用于在 Angular 应用程序中显示和交互数据列表。凭借其灵活性、定制选项以及与 Angular 的集成,它们为开发者提供了创建引人入胜且功能齐全的列表展示所需的一切。无论是需要简单的列表还是更复杂的交互,如重新排序和选择,PrimeNG 的列表组件都提供了一种强大的解决方案,可以增强任何应用程序的用户界面。
在下一节中,我们将介绍本章的最后一个组件:PrimeNG 卡片组件。
与卡片组件一起工作
PrimeNG 卡片是一个容器组件,它提供了一个灵活且可扩展的内容容器,具有多种变体和选项。它本质上是一个包含内容和关于单一主题的操作的矩形框。将其视为一个将特定信息组合在一起的小型容器。
卡片极其灵活,可以在各种场景中使用:
-
产品列表:卡片可以用于在线商店中显示产品,其中每个卡片代表一个带有图片、标题、价格和描述的产品
-
用户资料:在社交媒体平台上,卡片可以代表用户资料,展示图片、姓名和其他个人详情
-
博客文章:对于博客列表,每个卡片可能显示一篇文章的特色图片、标题和简短摘要
使用卡片可以将内容变得更加易于消化,将信息分解成易于一眼看懂的小块。
让我们深入一个实际例子。假设你正在构建一个在线商店,并希望使用 PrimeNG 的 Card 组件来显示产品列表。要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { CardModule } from 'primeng/card'
之后,我们添加 PrimeNG 的 Card 组件来创建产品列表:
<p-card
ngFor="let product of products"
[header]="product.name"
[style]="{ width: '300px' }"
>
<img
src="img/placeholder.png"
alt="{{ product.name }}"
style="width:100%"
/>
<div class="flex flex-column">
<p>{{ product.description }}</p>
<h3>\${{ product.price }}</h3>
<button pButton type="button" label="Add to Cart"></button>
</div>
</p-card>
这段代码展示了在 Angular 模板中使用 PrimeNG Card 组件的用法。让我们分析代码并解释每个部分:
-
<p-card>:这是 PrimeNGCard组件的开始,它代表一个单独的卡片元素 -
*ngFor="let product of products":这是一个名为ngFor的 Angular 结构性指令,用于遍历产品数组并为每个产品生成一张卡片 -
[header]="product.name":这会将product.name属性绑定到Card组件的标题输入,从而设置卡片的标题文本 -
[style]="{ width: '300px' }":这会将内联 CSS 样式绑定到Card组件的样式输入,将卡片的宽度设置为 300 像素
让我们看看最终结果:
图 6.15 – 卡片示例
在这个例子中,我们正在遍历产品列表并为每个产品创建一张卡片。每个卡片显示产品的图片、描述、价格以及一个“添加到 购物车”按钮。
我们最近学习了 PrimeNG 卡片组件的灵活性和设计特性,这大大提高了我们创建视觉上吸引人的用户界面的能力。现在,对我们来说,回顾和巩固我们的理解非常重要。
摘要
在本章中,我们深入探讨了 PrimeNG 的数据显示组件。我们首先理解了这些组件在将原始数据转换为有意义的、用户友好的信息中的作用,并看到了 PrimeNG 丰富的数据显示组件,如表格、列表和卡片,如何被用来在 Angular 应用程序中有效地展示数据。
本章获得的知识至关重要,因为有效的数据展示是构建用户友好应用的关键方面。通过使用 PrimeNG 的数据显示组件,我们可以创建不仅外观美观,而且提供无缝用户体验的应用程序。
但我们的旅程并未结束。展望下一章,我们将深入了解其他 PrimeNG 数据显示组件。我们将学习如何使用Tree、Scroller、Timeline和VirtualScroller等组件在我们的 Angular 应用程序中展示数据。
因此,让我们保持势头。我们在理解和使用 PrimeNG 的数据显示组件方面取得了巨大进步。现在,是时候迈出下一步,探索数据操作组件了。让我们继续进入下一章!
第七章:使用 Tree、TreeTable 和 Timeline 组件
应用程序中的数据展示不仅仅是表格、列表和卡片。有时,数据的本质需要更分层或按时间顺序的结构。这就是 Tree、TreeTable 和 Timeline 等组件发挥作用的地方。在本章中,我们将深入探讨这些专用组件,每个组件都提供独特的显示和交互方式,以使用 PrimeNG 在 Angular 应用程序中处理数据。
主要目标是熟悉专门针对特定数据展示需求的 PrimeNG 组件。随着我们进入本章,我们将掌握处理各种数据展示挑战的知识,以及如何在 Angular 应用程序中有效地实现它们。掌握这些组件意味着准备好提供增强用户体验和数据清晰度的解决方案。
在本章中,我们将涵盖以下主题:
-
使用 Tree 组件
-
使用 TreeTable 组件
-
使用 Timeline 组件
技术要求
本章包含各种 PrimeNG 显示组件的代码示例。您可以在以下 GitHub 仓库的 chapter-07 文件夹中找到相关源代码:github.com/PacktPublishing/Next-Level-UI-Development-with-PrimeNG/tree/main/apps/chapter-07。
使用 Tree 组件
PrimeNG Tree 组件是一个强大的工具,用于以有组织和视觉吸引力的方式显示分层数据,提供一种树状结构,其中数据可以呈现为节点,并且可以展开或折叠以显示或隐藏子节点。
在本节中,我们将探讨使用 PrimeNG Tree 组件的各个方面,包括其目的、用法和关键特性。该组件还提供了一系列功能,包括节点展开和折叠、选择模式、数据的懒加载、拖放功能以及上下文菜单支持,我们也将对其进行探讨。
何时使用 PrimeNG Tree 组件
PrimeNG 的 Tree 组件在需要以分层方式组织和展示数据的情况下特别有用。它通常用于处理类别、文件目录、组织结构以及其他表现出父子关系的任何数据。
例如,让我们考虑一个产品目录应用程序。目录可能包含类别、子类别和按层次结构组织的产品。在这种情况下,PrimeNG Tree 组件可以用来直观地表示产品目录,使用户能够浏览类别和子类别,并选择特定的产品。
创建基本的 Tree 组件
为了更好地理解如何使用 PrimeNG Tree 组件,让我们看一下前一个部分提到的产品目录示例。假设我们为我们的产品有以下层次结构:
- Electronics
- Computers
- MacBook Air
- Smartphone
- Phones
- iPhone
- Samsung
- Google Pixel
- Home & Garden
- Outdoor
- Furniture
- Office
- Books & Media
- Books
- Movies & TV
使用 PrimeNG Tree 组件,我们可以表示这种层次结构。
要开始使用,我们需要从 PrimeNG 库中导入必要的模块:
import { TreeModule } from 'primeng/tree'
一旦安装并导入了依赖项,我们就可以在 Angular 模板中使用 Tree 组件。以下是如何以树布局显示产品的示例:
// tree.component.ts
import { TreeNode } from 'primeng/api'
// Html / template
<p-tree [value]="products" />
// TypeScript
products: TreeNode[] = [
{
"key": "0",
"label": "Electronics",
"data": "Category Level",
"icon": "pi pi-tablet",
"children": [
{
"key": "0-0",
"label": "Computers",
"data": "SubCategory Level",
"icon": "pi pi-desktop",
"children": [
{
"key": "0-0-0",
"label": "MacBook Air",
"data": "Product Level",
"icon": "pi pi-apple"
},
...
]
},
...
]
}
...
]
让我们分解一下代码:
-
<p-tree [value]="products" />:这表示了 PrimeNGTree组件的使用。它将Tree组件的value属性绑定到products变量。 -
Products: TreeNode[]:这定义了products变量为TreeNode对象的数组。TreeNode是 PrimeNG 定义的一种类型,用于在树组件中表示节点。每个TreeNode对象具有以下属性:-
key:节点的唯一标识符。 -
label:将显示在节点上的文本。 -
data:与节点相关联的附加数据。在这个例子中,它表示节点的级别(类别级别、子类别级别或产品级别)。 -
icon:与节点相关联的可选图标。 -
children:子节点的数组。此属性允许树具有嵌套结构。
-
这是一个表示商店的简化树结构的示例。以下是结果:
图 7.1 – 基本树
展开和折叠节点
PrimeNG Tree 组件的一个基本特性是能够展开和折叠节点。这使用户能够根据兴趣在树中导航,显示或隐藏子节点。
默认情况下,PrimeNG Tree 组件以所有节点折叠的状态开始。用户可以通过点击其展开图标来展开一个节点,也可以通过点击其折叠图标来折叠一个节点。
除了用户交互之外,您还可以通过操作节点的状态来以编程方式控制节点的展开和折叠。例如,您可以使用 expandAll() 和 collapseAll() 方法分别以编程方式展开所有节点或折叠所有节点。
下面是一个演示展开和折叠功能的示例:
// tree.component.ts
<div class="grid gap-2 p-2 mb-2">
<button
pButton
type="button"
label="Expand all"
(click)="expandAll()"
></button>
<button
pButton
type="button"
label="Collapse all"
(click)="collapseAll()"
></button>
</div>
<p-tree [value]="products" />
...
expandAll() {
this.products.forEach((node) => {
this.expandRecursive(node, true)
})
}
collapseAll() {
this.products.forEach((node) => {
this.expandRecursive(node, false)
})
}
private expandRecursive(node: TreeNode, isExpand: boolean) {
node.expanded = isExpand
if (node.children) {
node.children.forEach((childNode) => {
this.expandRecursive(childNode, isExpand)
})
}
}
在这里,我们向 UI 中添加了两个按钮用于展开和折叠节点。expandAll() 和 collapseAll() 方法分别绑定到相应按钮的点击事件。当用户点击展开全部按钮时,树中的所有节点都将展开,而当点击折叠全部按钮时,所有节点都将折叠。
expandRecursive(...) 方法是一个私有方法,它递归地展开或折叠树中的节点。它接受一个 TreeNode 对象(node)和一个布尔值(isExpand)作为参数,并将 node 的 expanded 属性设置为 isExpand 的值,从而展开或折叠节点。
点击 展开 全部 按钮的结果如下:
图 7.2 – 带展开和折叠能力的树
使用节点选择事件
PrimeNG Tree 组件提供了一系列事件和方法,允许你与组件交互并响应用户操作。这些事件和方法使你能够执行诸如处理节点选择、捕获节点展开和折叠事件以及动态加载数据等任务。
在启用节点选择事件之前,我们需要向组件添加 selectionMode。有四种选择类型:
-
<p-tree [value]="products"selectionMode="single" />。 -
<p-tree [value]="products"selectionMode="single"[metaKeySelection]="true"/>。 -
<p-tree [value]="products"selectionMode="multiple" />。 -
<p-tree [value]="products"selectionMode="checkbox" />。
在添加节点选择类型后,PrimeNG Tree 组件在节点被选择或取消选择时发出事件。你可以使用这些事件根据用户的节点选择执行操作。
要捕获节点选择事件,你可以使用 (onNodeSelect) 和 (onNodeUnselect) 事件绑定。以下是一个 single 选择示例:
// tree.component.ts
<p-tree
[value]="products"
selectionMode="single"
(onNodeSelect)="onNodeSelected($event)"
(onNodeUnselect)="onNodeUnselected($event)"
/>
...
onNodeSelected(event: TreeNodeSelectEvent) {
console.log(event)
}
onNodeUnselected(event: TreeNodeSelectEvent) {
console.log(event)
}
在代码中,(onNodeSelect) 事件绑定到 onNodeSelected() 方法,而 (onNodeUnselect) 事件绑定到 onNodeUnselected() 方法。当节点被选择或取消选择时,这些方法将被调用。
让我们看看选择 Electronics 节点时的一个示例事件:
图 7.3 – 带选择事件的树
因此,我们可以看到在选择具有以下详细信息的 node 数据后:
-
expanded: true:这表示当前节点处于展开状态 -
parent: undefined:这表明当前节点没有父节点 -
data, icon, key, label, children:这显示了当前节点的现有值
使用节点展开和折叠事件
当节点展开或折叠时,PrimeNG Tree 组件会发出事件。你可以利用这些事件在用户展开或折叠节点时执行操作。
要捕获节点展开或折叠事件,你可以使用 (onNodeExpand) 和 (onNodeCollapse) 事件绑定。以下是一个示例:
// tree.component.ts
<p-tree
[value]="productsWithEvents"
(onNodeExpand)="onNodeExpanded($event)"
(onNodeCollapse)="onNodeCollapsed($event)"
/>
...
onNodeExpanded(event: TreeNodeSelectEvent) {
console.log(event)
}
onNodeCollapsed(event: TreeNodeSelectEvent) {
console.log(event)
}
在这里,(onNodeExpand) 事件绑定到 onNodeExpanded() 方法,而 (onNodeCollapse) 事件绑定到 onNodeCollapsed() 方法。这些方法将在节点展开或折叠时分别被触发。展开或折叠后的事件值与选择或取消选择节点时的值相同。
懒加载的工作方式
PrimeNG 的 Tree 组件支持数据的懒加载,这在处理大数据集时非常有用。您不必一次性加载所有节点,而可以在用户展开节点时动态加载节点。
要启用懒加载,您需要使用 [loading] 属性和 (onNodeExpand) 事件。[loading] 属性允许您指示树是否正在加载数据,而 (onNodeExpand) 事件在节点展开时触发,允许您动态加载子节点。
这里有一个演示懒加载的例子:
<p-tree
[loading]="loading"
[value]="products"
(onNodeExpand)="loadChildNodes($event)"
/>
...
loading = false
loadChildNodes(event: TreeNodeSelectEvent) {
if (event.node) {
this.loading = true
// example of retrieving child nodes data
event.node.children = this.nodeService.getChildNodes(event.node)
this.loading = false
}
}
在前面的代码中,[loading] 属性绑定到 Angular 组件中的 loading 变量,该变量指示树是否正在加载数据。(onNodeExpand) 事件绑定到 loadChildNodes() 方法,该方法负责加载展开节点的子节点。以下是结果:
图 7.4 – 带加载的树
注意
应在 Angular 组件中实现 loadChildNodes() 方法,以便根据展开的节点动态获取子节点。
在本节中,我们讨论了何时使用 PrimeNG Tree 组件,例如在需要按层次组织数据的情况下,如产品目录或文件系统,以及它的各种功能。在下一节中,我们将深入了解 TreeTable 组件。
与 TreeTable 组件一起工作
当涉及到以表格格式展示层次数据结构时,PrimeNG 的 TreeTable 成为了一个强大的工具,它结合了两个世界的最佳之处:树的嵌套结构和表格的有序列。让我们开始一段旅程,更好地理解这个组件,并看看它如何提升我们的数据展示水平。
何时使用 PrimeNG TreeTable 组件
PrimeNG 的 TreeTable 组件在需要表示具有层次结构的数据的场景中特别有用。它提供了一种直观且用户友好的方式来导航和交互层次数据,使其非常适合处理组织结构、文件系统、产品类别以及其他表现出父子关系的任何数据的应用程序。
TreeTable 组件更适合以表格格式展示具有高级交互选项(如排序、过滤和分页)的层次数据,而 Tree 组件最适合以紧凑且可折叠的树形结构显示和导航层次数据。
通过利用 TreeTable 组件,你可以以结构化和组织的方式展示复杂层次数据,使用户能够展开和折叠节点,执行排序和过滤操作,并以无缝的方式与数据交互。
创建一个基本的 TreeTable 组件
假设你有一个产品列表,这些产品被归类在不同的产品系列下。每个产品都有价格、可用性和评分等详细信息。TreeTable 组件可以是一个很好的选择来表示这些数据。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { TreeTableModule } from 'primeng/treetable'
一旦安装并导入了依赖项,我们就可以在我们的 Angular 模板中使用 TreeTable 组件。以下是如何在 TreeTable 布局中显示产品的示例:
<p-treeTable
[value]="products"
[scrollable]="true"
[tableStyle]="{ 'min-width': '50rem' }"
>
<ng-template pTemplate="header">
<tr>
<th>Name</th>
<th>Price (USD)</th>
<th>Rating</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-rowNode let-product="rowData">
<tr [ttRow]="rowNode">
<td>
<p-treeTableToggler [rowNode]="rowNode" />
{{ product.name }}
</td>
<td>{{ product?.price | currency }}</td>
<td>{{ product?.rating }}</td>
</tr>
</ng-template>
</p-treeTable>
...
products: TreeTableNode[] = [
{
"key": "0",
"data": {
"name": "Electronics"
},
"children": [
{
"key": "0-0",
"data": {
"name": "Computers"
},
"children": [
{
"key": "0-0-0",
"data": {
"id": 1,
"name": "MacBook Air",
"price": 999,
"description": "Light and portable MacBook",
"quantity": 100,
"rating": 4,
"category": "Computers"
}
},
...
]
}
]
}
...
]
让我们分解一下代码:
-
<p-treeTable>: 这是 PrimeNG 库中的 Angular 组件,用于以树状结构显示层次表格数据。 -
[value]="products": 此属性绑定将products属性设置为TreeTable组件的数据源。组件代码中的products变量包含一个TreeTableNode对象数组,代表层次数据结构。 -
[scrollable]="true": 此属性绑定启用TreeTable组件内的滚动,如果内容超出可用空间。 -
[tableStyle]="{ 'min-width': '50rem' }": 此属性绑定将内联 CSS 样式对象应用于<p-treeTable>组件的tableStyle属性。在这种情况下,它将TreeTable组件的最小宽度设置为50rem。 -
<ng-template pTemplate="header">: 此元素定义了一个用于渲染TreeTable组件的标题行的模板。 -
<ng-template pTemplate="body" let-rowNode let-product="rowData">: 此元素定义了一个用于渲染TreeTable组件的体(行)的模板。此模板还具有两个其他属性:-
let-rowNode: 这声明了一个名为rowNode的局部变量,它代表正在渲染的当前行节点 -
let-product="rowData": 这声明了一个名为product的局部变量,它代表与当前行关联的数据
-
-
<p-treeTableToggler [rowNode]="rowNode" />: 此组件用于在TreeTable组件中显示用于展开和折叠子节点的切换按钮。 -
products: TreeTableNode[]: 这定义了products数组作为TreeTable组件的数据源。products数组由TreeTableNode对象组成,代表层次数据结构。每个节点都有一个包含产品信息的数据属性,例如name、price、rating和category。示例显示了一个嵌套结构,其中包含一个父节点Electronics和一个子节点Computers,它进一步包含一个具有相应属性的MacBook Air子节点。
这是一个表示商店的简化 TreeTable 结构的示例。以下是结果:
图 7.5 – 基本的 TreeTable 结构
使用动态列
TreeTable 组件允许我们根据提供的数据或配置动态创建列。而不是在模板中手动定义每个列,我们可以绑定来自组件的列集合,并让TreeTable组件动态生成必要的列。这种方法不仅高效,而且提供了高度的灵活性。
让我们考虑一个电子商务应用的例子,该应用以TreeTable格式显示产品。该应用需要处理不同的产品类别,每个类别都有自己的属性集。目标是根据所选的产品类别动态渲染列。以下是代码:
<div class="grid gap-4 ml-0 mb-4">
<button
(click)="updateColumns('RATING')"
pButton
label="Rating"
></button>
<button
(click)="updateColumns('QUANTITY')"
pButton
label="Quantity"
></button>
</div>
<p-treeTable
[value]="products"
[columns]="cols"
[scrollable]="true"
[tableStyle]="{ 'min-width': '50rem' }"
>
<ng-template pTemplate="header" let-columns>
<tr>
<th *ngFor="let col of columns">
{{ col.header }}
</th>
</tr>
</ng-template>
<ng-template
pTemplate="body"
let-rowNode
let-product="rowData"
let-columns="columns"
>
<tr>
<td *ngFor="let col of columns; let i = index">
<p-treeTableToggler [rowNode]="rowNode" *ngIf="i === 0" />
{{ product[col.field] }}
</td>
</tr>
</ng-template>
</p-treeTable>
...
cols = [
{ field: 'name', header: 'Name' },
{ field: 'price', header: 'Price' },
{ field: 'rating', header: 'Rating' },
]
updateColumns(option: string) {
switch (option) {
case 'RATING':
this.cols = [
{ field: 'name', header: 'Name' },
{ field: 'price', header: 'Price' },
{ field: 'rating', header: 'Rating' },
]
break
case 'QUANTITY':
this.cols = [
{ field: 'name', header: 'Name' },
{ field: 'price', header: 'Price' },
{ field: 'quantity', header: 'Quantity' },
]
break
default:
break
}
}
让我们分解一下代码:
-
<button (click)="updateColumns(...)" >:这是一个按钮元素,当点击时触发updateColumns()方法。 -
<th *ngFor="let col of columns">{{ col.header }}</th>:这一行使用*ngFor指令遍历columns数组并为每个列生成一个<th>元素。列的header属性作为header单元格的内容显示。 -
<td *ngFor="let col of columns; let i = index">:这一行使用*ngFor指令遍历columns数组并为每个列生成一个<td>元素。 -
<p-treeTableToggler [rowNode]="rowNode" *ngIf="i === 0" />:这个<p-treeTableToggler>组件用于在TreeTable组件中显示一个切换按钮,用于展开和折叠子节点。
使用这种实现,TreeTable将根据所选类型显示适当的产品数据列。让我们看看结果:
图 7.6 – 带有动态列的 TreeTable
如果用户从评分类型切换到数量类型,表格将自动更新以显示数量列而不是评分,如图 7.5 所示。
启用 TreeTable 分页器
TreeTable 组件允许我们将大量数据分解成更小、更易于管理的块或页面。而不是一次性显示数百或数千行,分页器允许用户逐页浏览数据。它提供了移动到下一页或上一页、跳转到开始或结束以及选择页面大小的控件。
我们可以通过添加paginator和rows属性轻松地在TreeTable组件中启用分页器,如下面的代码所示:
<p-treeTable [value]="products" [paginator]="true" [rows]="2">
<!-- Column templates and other TreeTable configurations go here -->
</p-treeTable>
在这个例子中,我们通过设置[paginator]="true"并指定每页显示两行来启用分页,[rows]="2"。
现在,TreeTable 组件将显示分页控件,用户可以逐页浏览产品数据:
图 7.7 – 带分页器的树表
相关事件和方法
TreeTable 组件提供了各种事件和方法,您可以利用这些来增强您应用程序的功能性和交互性。以下是一些常用的事件和方法:
-
onNodeExpand: 当节点被展开时触发此事件 -
onNodeCollapse: 当节点折叠时触发此事件 -
onNodeSelect: 当选择一个节点时触发此事件 -
onNodeUnselect: 当节点被取消选择时触发此事件
您可以使用这些事件和方法根据您应用程序的需求自定义TreeTable组件的行为。例如,您可以通过监听onNodeCollapse事件在节点折叠时执行某些操作,例如删除详细信息或触发附加操作:
<p-treeTable
[value]="files"
(onNodeCollapse)="handleNodeCollapse($event)"
>
<!-- Column templates and other TreeTable configurations -->
</p-treeTable>
...
handleNodeCollapse(event: TreeTableNodeCollapseEvent) {
const collapsedNodeData = event.node.data
// Handle actions when a node is collapsed
}
让我们分解一下代码:
-
(onNodeCollapse)="handleNodeCollapse($event)": 这将handleNodeCollapse方法绑定到TreeTable组件中节点折叠时发生的事件。该方法将使用event对象作为参数被调用。 -
handleNodeCollapse(event: TreeTableNodeCollapseEvent) { ... }: 这接受一个TreeTableNodeCollapseEvent类型的event对象作为参数。这个event对象包含了有关折叠节点的信息,您可以使用这些信息来处理事件。
在我们探索 PrimeNG 的 TreeTable 组件过程中,我们已经看到了它在以结构化和用户友好的方式呈现层次化数据方面的强大功能。从动态列到高效的分页,TreeTable 组件为各种数据表示挑战提供了一个强大的解决方案。现在,让我们将焦点转移到 PrimeNG 的 Timeline 组件上,这是一个能够以时间顺序美妙的可视化数据的工具。
使用时间线组件
PrimeNG 的 Timeline 组件是 Angular 应用程序中由 PrimeNG 库提供的强大组件,它允许您按时间顺序可视化一系列连锁事件。时间轴提供了一种用户友好且交互式的显示事件的方式,使用户更容易理解活动或随时间变化的顺序。
PrimeNG 的 Timeline 组件旨在以线性方式呈现事件,使用户能够浏览不同的阶段或里程碑。时间线中的每个事件都由一个标记表示,该标记可以自定义以显示相关信息,例如状态、日期或任何其他有意义的资料。
时序图提供了各种功能来增强用户体验——它支持垂直和水平布局,提供了时序图方向的灵活性,以及对齐选项来定位时序图条相对于内容的位置。
当使用 PrimeNG 时序图组件时
PrimeNG 的 Timeline 组件可以在各种应用程序和场景中使用。以下是一些 Timeline 组件可能有益的示例:
-
项目管理:使用时序图来展示项目里程碑,例如项目启动、需求收集、开发阶段和项目完成。这有助于利益相关者和团队成员可视化项目的进度并理解关键事件的顺序。
-
订单跟踪:如果您有一个电子商务应用程序,可以利用时序图来显示订单处理的各个阶段,如订单提交、支付验证、订单履行和交付。这为顾客提供了一个清晰的订单进度概览。
-
历史事件:时序图也适合展示历史事件或重大成就。例如,您可以使用它来展示科学发现的时序、重大历史事件或特定行业的演变。
-
产品更新:如果您维护产品路线图或想展示软件产品的发布历史,时序图可以是一种有效的方式来展示随时间推移的不同版本、更新和新功能。
每当需要按事件发生的顺序表示一系列事件时,PrimeNG 的 Timeline 组件是一个极佳的选择。
创建基本时序图
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { TimelineModule } from 'primeng/timeline'
一旦我们安装并导入了依赖项,我们就可以在 Angular 模板中使用 Timeline 组件。以下是一个如何在时序图布局中显示订单状态的示例:
<p-timeline [value]="orderStatuses">
<ng-template pTemplate="content" let-order>
<span [class]="order.icon"></span>
{{ order.title }}
</ng-template>
</p-timeline>
...
orderStatuses = [
{
title: 'Order Placed',
content: 'Your order has been received and is being processed.',
icon: 'pi pi-shopping-cart',
},
{
title: 'Order Confirmed',
content:
'Your payment has been confirmed and the order is now being prepared.',
icon: 'pi pi-check-square',
},
{
title: 'In Warehouse',
content: 'Your product is in the warehouse, awaiting dispatch.',
icon: 'pi pi-globe',
},
{
title: 'Shipped',
content:
'Your order has been shipped and is on its way to the delivery address.',
icon: 'pi pi-truck',
},
{
title: 'Out for Delivery',
content: 'The product is out for delivery and will reach you soon.',
icon: 'pi pi-map-marker',
},
{
title: 'Delivered',
content: 'Your product has been successfully delivered. Enjoy!',
icon: 'pi pi-check-circle',
},
]
让我们分解代码并理解其功能:
-
<p-timeline [value]="orderStatuses">:这代表了 PrimeNG 的Timeline组件的使用。它将Timeline组件的value属性绑定到orderStatuses变量。 -
<ng-template pTemplate="content" let-order>:这定义了在时序图中渲染每个状态内容的模板。 -
orderStatuses:这代表订单的不同阶段或状态。数组中的每个元素对应将在时序图中显示的特定事件。
总体而言,代码展示了如何使用 PrimeNG 的 Timeline 组件来显示订单状态的时序图。时序图通过 orderStatuses 数组中的状态数据填充,每个状态都使用包含图标和标题的模板进行渲染。这允许以直观且信息丰富的方式按时间顺序展示事件。
下面是代码的结果:
图 7.8 – 基本时间线
时间线对齐
PrimeNG 的时间线对齐功能允许您控制内容相对于时间线的位置。您可以将内容对齐到时间线的左侧、右侧、顶部、底部或交替侧。这种灵活性允许您根据您的设计偏好或应用需求自定义时间线的外观和布局。
让我们想象我们正在构建一个时间线来展示产品的订单状态。您可以通过选择align属性的不同的值来自定义对齐方式,例如left、right或alternate,具体取决于您的特定设计要求。让我们更新我们现有的订单状态时间线的对齐方式:
<p-timeline [value]="orderStatuses" align="alternate">
// timeline content
</p-timeline>
在代码片段中,我们使用了align属性并设置为alternate值,以使每个活动的内容在时间线线的交替两侧对齐。这种布局创建了一个有趣的视觉模式,活动出现在时间线的左右两侧:
图 7.9 – 时间线对齐
时间线水平布局
除了对齐选项之外,PrimeNG 的Timeline组件还提供了一个水平布局选项。水平布局旨在从左到右线性地展示事件或里程碑,这在您想要展示跨越广阔区域的时间线时尤其有用,例如项目时间线或历史事件序列。
要使用具有水平布局的Timeline,您可以在Timeline组件中将layout属性设置为horizontal。让我们看看一个例子:
<p-timeline [value]="orderStatuses" layout="horizontal">
// timeline content
</p-timeline>
在代码片段中,我们将layout属性设置为horizontal,表示我们希望以水平方式显示时间线事件。以下是结果:
图 7.10 – 水平时间线
通过我们对 PrimeNG 的Timeline组件的探索,我们看到了它如何提供一种动态的方式来视觉表示事件、里程碑或过程。它的灵活性,从基本事件表示到对齐或布局等特性,确保我们可以根据我们的需求定制叙述。在我们结束这一节的时候,让我们花点时间回顾我们的旅程并总结关键要点。
摘要
在本章中,我们探讨了使用 PrimeNG 的Tree、TreeTable和Timeline组件表示层次和时序数据的复杂性。这些强大的工具在以视觉吸引力和用户友好的方式展示结构化数据方面发挥着关键作用,无论是显示项目的层次结构还是可视化随时间推移的事件序列。
我们从揭示Tree组件的能力和了解其在有效表示父子关系数据中的重要性开始。TreeTable组件在此基础上扩展了这一概念,通过提供表格和层次数据展示的无缝集成。此外,Timeline组件展示了其在按时间顺序可视化序列、里程碑或事件方面的能力,为我们提供了清晰和连贯地呈现叙事或流程的灵活性。
通过掌握这些组件,我们为自己配备了有效以直观方式呈现复杂数据结构的必要工具。这不仅提升了用户体验,还确保了我们的应用既实用又美观。
随着我们为下一次旅程做好准备,我们将深入探讨另一组 PrimeNG 组件,这些组件将进一步提升我们应用的用户交互性和功能性。准备好在下一章探索导航和布局组件。
第八章:与导航和布局组件一起工作
在 Web 应用程序中导航应该是一个无缝的体验。我们如何构建内容、引导用户以及响应他们的交互可以显著影响他们的整体体验。本章深入探讨了 PrimeNG 的导航和布局组件,旨在帮助我们为 Angular 应用程序构建直观且用户友好的界面。
在这次探索中,我们将揭示 PrimeNG 导航组件的潜力,了解它们如何被用来引导用户通过我们的应用程序。从菜单到面包屑,从标签页到手风琴,我们将学习如何构建内容结构,创建导航路径,并设计适应不同屏幕尺寸的响应式布局。
本章的整体目标是赋予你利用 PrimeNG 的导航和布局组件的有效知识和技术。到本章结束时,你将能够创建无缝的导航体验,以结构化的方式组织内容,并确保适应各种设备的响应式布局。你还将深入了解如何处理导航事件并将它们集成到应用程序的功能中。
在本章中,我们将涵盖以下主题:
-
介绍导航和布局组件
-
与菜单一起工作
-
介绍 PrimeNG 面板
技术要求
本章包含 PrimeNG 显示组件的各种代码示例。你可以在以下 GitHub 仓库的chapter-08文件夹中找到相关源代码:github.com/PacktPublishing/Next-Level-UI-Development-with-PrimeNG/tree/main/apps/chapter-08
介绍导航和布局组件
在 Web 开发领域,创建直观且用户友好的界面对于为用户提供无缝体验至关重要。导航和布局组件在实现这一目标中发挥着关键作用。这些组件作为组织内容、引导用户通过应用程序的不同部分以及确保响应式设计的构建块。
导航和布局组件是什么?
导航组件为用户提供了一种在应用程序的各个功能、部分和内容之间导航的方式。它们提供了直观且易于访问的方法来访问不同的功能,从而提高了应用程序的整体可用性。导航组件的例子包括菜单、面包屑、标签页和工具栏。
另一方面,布局组件负责在应用程序中构建和组织内容的展示。它们确保信息以清晰和视觉上吸引人的方式显示。布局组件为创建能够适应不同屏幕尺寸和设备的响应式和自适应设计提供了基础。
打造直观的导航和布局体验
创建直观的导航系统就像设计一个城市的道路网络。它应该是逻辑的,易于遵循,并满足用户的需求。以下是一些可以帮助您实现这一目标的要点:
-
以用户为中心的设计:始终以用户为中心进行设计。了解他们的需求、习惯和期望。与用户直觉产生共鸣的导航系统总是更有效。
-
一致性是关键:无论是导航按钮的位置还是下拉菜单的样式,在整个应用程序中保持一致性有助于用户建立熟悉感。
-
反馈:当用户与导航元素互动时提供反馈。无论是按钮在悬停时改变颜色,还是菜单打开时的微妙动画,这些小交互都可以增强用户体验。
-
适应性:确保您的导航和布局组件是响应式的,适应不同的屏幕尺寸和设备,无论在桌面、平板电脑还是手机上查看,都能提供无缝的体验。
创建导航和布局组件的最佳实践
在创建导航和布局组件时,以下是一些需要记住的额外最佳实践:
-
简洁性:过度复杂的导航会使用户困惑;追求清晰和易用性。
-
模块化:将复杂的导航和布局结构分解成更小、可重用的组件。这促进了代码的可重用性、可维护性和可扩展性。
-
可访问性:确保您的导航组件对所有人都是可访问的,包括有残疾的人。使用语义 HTML,为图像提供 alt 文本,并确保组件是键盘可导航的。
-
测试:测试您的导航组件。这可以通过可用性测试来完成,其中真实用户与您的应用程序互动。他们的反馈可以提供宝贵的见解,以改进您的组件。
请记住,这些最佳实践作为指南,根据您应用程序的具体需求和需求进行调整至关重要。现在,让我们继续探讨构建 Angular 应用程序中直观 UI 的另一个重要方面:PrimeNG 菜单。
与菜单一起工作
菜单是 UI 的一个基本元素,它提供了导航结构,并允许用户访问应用程序的各种功能和功能。在 PrimeNG 中,您可以找到各种菜单组件,可以轻松集成到您的项目中。在本节中,我们将探讨菜单是什么,讨论何时使用 PrimeNG 菜单,并提供在电子商务应用程序中使用 PrimeNG 菜单的示例。
PrimeNG 菜单是什么?
菜单的复杂性和设计各不相同,从简单的基于文本的菜单到更复杂的具有子菜单和图标的分层菜单。PrimeNG 提供了一系列菜单组件,以满足不同的用例和设计需求。PrimeNG 提供的以下是一些流行的菜单组件:
-
Menu:p-menu组件是一个多功能的菜单,支持多种模式,如弹出、滑动和覆盖。它可以作为一个独立的菜单或作为其他组件中的下拉菜单使用。 -
Menubar:p-menubar组件代表一个水平菜单栏,通常用于顶级导航场景。它允许您创建一个干净且简洁的导航界面,特别适用于具有多个部分或模块的应用程序。 -
MegaMenu:p-megaMenu组件是为更复杂的导航场景设计的,允许您创建带有图片、图标和子菜单的多列菜单。 -
ContextMenu:p-contextMenu组件允许显示上下文特定的菜单,当用户在元素上右键点击或长按时出现。它对于提供上下文相关的操作或选项非常有用。 -
TieredMenu:p-tieredMenu组件是一个支持多级嵌套菜单的层次菜单。它适合以结构化的方式组织选项。 -
Breadcrumb:p-breadcrumb组件用于显示表示用户在应用程序层次结构中当前位置的面包屑导航路径。它通常放置在页面顶部附近,并提供链接到高级别部分或页面。
这些只是 PrimeNG 中可用的菜单组件的几个示例。根据您应用程序的需求,您可以选择最合适的菜单组件来创建无缝且直观的导航体验。
创建基本菜单
假设您想在电子商务应用程序主页的顶部添加一个水平菜单。此菜单包括电子产品、服装、家居和厨房以及运动和健身等类别,每个类别代表一个当用户悬停或点击时展开的下拉菜单。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import {MenuModule} from 'primeng/menu'
一旦安装并导入了依赖项,让我们看看如何设置 PrimeNG 菜单:
import { MenuItem } from 'primeng/api'
<p-menu [model]="menuItems" />
...
menuItems: MenuItem[] = [
{
label: 'Electronics',
items: [
{ label: 'Computers', routerLink: '/products/computers' },
{ label: 'Smartphones', routerLink: '/products/smartphones' },
{ label: 'Televisions', routerLink: '/products/televisions' },
],
},
...
]
让我们分解一下代码:
-
<p-menu [model]="menuItems" />:这表示 PrimeNGMenu组件的使用。它将Menu组件的model属性绑定到menuItems变量。 -
menuItems: MenuItem[]:这是一个来自 PrimeNG API 的MenuItem对象数组。每个MenuItem对象可以具有各种属性,例如label、items、routerLink、routerLinkActiveOptions等。
注意
菜单项中的routerLink属性是 Angular 的一个特性,它简化了应用程序中不同路由之间的导航。routerLinkActiveOptions属性提供了一种通过针对p-menuitem-link-active类来验证和样式化活动菜单的方法。默认情况下,活动类应用于与MenuItem对象中定义的routerLink值匹配的路由。如果您需要不同的配置,请参阅angular.io/api/router/IsActiveMatchOptions上的文档。
在本例中,每个菜单项都由一个label属性表示,该属性指定要显示的文本。items属性表示每个类别的子菜单项。然后使用routerLink属性在点击项时导航到相应的产品列表页面。以下是结果:
图 8.1 – 基本菜单
使用 Menubar
PrimeNG Menubar是一个为水平布局设计的动态导航组件。它不仅是一个链接列表,还提供了定制选项以满足不同的应用程序需求。您可以在Menubar中包含链接、按钮和其他 UI 组件,使其变得灵活且适应性强。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { MenubarModule } from 'primeng/menubar'
之后,我们可以通过使用 PrimeNG 的p-menubar组件来创建菜单栏:
<p-menubar [model]="menuItems" />
让我们看看结果:
图 8.2 – Menubar
在本例中,Menubar包含两个主要部分:电子产品和服装。电子产品部分进一步细分为电脑、智能手机和电视等子类别。这种结构确保用户可以迅速导航到他们想要的产品类别或轻松访问他们的账户设置,而无需任何麻烦。
使用 MegaMenu
PrimeNG MegaMenu是一个下拉导航组件,在二维面板中显示子菜单,非常适合具有大量导航选项的情况,消除了滚动长列表的需求。它对于具有多个功能或类别的网站或应用程序特别有用,提供了有组织和易于访问的导航选项。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { MegaMenuModule } from 'primeng/megamenu'
之后,我们可以通过使用 PrimeNG 的p-megaMenu组件来创建菜单栏:
<p-megaMenu [model]="megaMenuItems" />
...
megaMenuItems: MegaMenuItem[] = [
{
label: 'Categories',
items: [
[
{
label: 'Electronics',
items: [
{ label: 'Laptops', routerLink: '/electronics/laptops' },
{ label: 'Cameras', routerLink: '/electronics/cameras' },
],
},
...
],
],
},
...
]
在本例中,我们定义了一个MegaMenuItem对象的数组来表示菜单结构。每个MenuItem对象都有一个label属性来指定菜单项显示的文本。此外,items属性用于在菜单项内嵌套子菜单。生成的MegaMenu组件将有一个顶级名为类别:
图 8.3 – MegaMenu
当用户将鼠标悬停在类别上时,将出现一个下拉子菜单,包含额外的子类别和产品。在这个例子中,在悬停之后,你可以看到电子产品、时尚和家居与生活子类别。在电子产品子类别中,还有进一步的选择:笔记本电脑和相机。
与 ContextMenu 一起工作
PrimeNG ContextMenu是一个上下文菜单组件,在用户执行特定操作(通常是右键点击)时在 UI 中弹出。它提供了一系列用户可以执行的操作,这些操作与用户交互的区域或元素上下文相关。与导航到顶级菜单或搜索选项不同,上下文菜单将操作直接带到用户面前。
当你想为用户提供快速操作而不使 UI 杂乱无章时,会使用上下文菜单。在以下情况下特别有益:
-
屏幕空间有限
-
你希望提供与特定元素或区域相关的选项
-
你的目标是减少用户需要点击的次数
例如,在文本编辑器中,右键点击可能会弹出剪切、复制或粘贴的选项。在图片查看器中,它可能提供缩放、保存或分享的选项。
让我们设想一个电子商务平台,用户可以在其中浏览产品。上下文菜单可以为这些产品提供快速操作。要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { MegaMenuModule } from 'primeng/megamenu'
之后,让我们为产品图片创建一个上下文菜单:
<img
#img
src="img/placeholder.png"
alt="Product"
aria-haspopup="true"
class="max-w-full"
/>
<p-contextMenu [target]="img" [model]="contextMenuItems" />
...
contextMenuItems: MenuItem[] = [
{
label: 'View Details',
icon: 'pi pi-search',
command: (event) => this.viewProduct(event.item),
},
{
label: 'Add to Cart',
icon: 'pi pi-shopping-cart',
command: (event) => this.addToCart(event.item),
},
{
label: 'Add to Wishlist',
icon: 'pi pi-heart',
id: 'wishlist',
command: (event) => this.addToWishlist(event.item),
},
]
viewProduct(item: MenuItem) {
// Logic to view product details
}
addToCart(item: MenuItem) {
// Logic to add product to cart
}
addToWishlist(item: MenuItem) {
// Logic to add product to wishlist
}
让我们分解一下代码:
-
<img #img .../>:这是一个模板引用变量,用于在 Angular 组件中引用<img>元素 -
<p-contextMenu [target]="img" [model]="contextMenuItems" />:这部分代码定义了 PrimeNG 的ContextMenu组件并配置了其属性:-
[target]="img":这会将ContextMenu组件的目标属性绑定到img模板引用变量。这意味着当用户右键点击引用的<img>元素时,ContextMenu组件将被触发。 -
[model]="contextMenuItems":这会将ContextMenu的model属性绑定到contextMenuItems数组。 -
contextMenuItems: MenuItem[]:这是一个MenuItem对象的数组。每个对象代表上下文菜单中的一个菜单项。它具有如label(显示在菜单项上的文本)、icon(与菜单项关联的图标)和command(当选择菜单项时要执行的功能)等属性。在这种情况下,command属性被设置为调用 Angular 组件中的特定方法(viewProduct()、addToCart()和addToWishlist())。
-
让我们看看结果:
图 8.4 – ContextMenu 示例
在这个设置中,当用户在产品上右键点击时,他们会看到查看详情、添加到购物车或添加到愿望单的选项。这增强了购物体验,使操作迅速而直接。
与TieredMenu一起工作
PrimeNG 的TieredMenu是一个多级菜单系统,允许选项以分层结构组织。与扁平列表不同,您会得到一个级联菜单,其中选项可以有子选项,这些子选项还可以有自己的子选项,依此类推。这种分层结构在视觉上直观,使用户能够轻松地浏览类别和子类别。
PrimeNG 的TieredMenu在各种需要分层导航菜单的场景中都是一个很好的选择。以下是一些您可以利用TieredMenu功能的情况:
-
复杂的应用程序菜单:当您有一个包含大量菜单项和子菜单的应用程序时,
TieredMenu简化了菜单结构和管理的组织。它允许您创建一个逻辑上的菜单层次结构,使用户能够更容易地浏览应用程序。 -
电子商务网站:
TieredMenu在电子商务网站上特别有用,因为它们通常有广泛的产品类别和子类别。通过使用TieredMenu,您可以创建一个用户友好的导航系统,使购物者能够轻松浏览不同的产品类别和子类别。 -
管理仪表板:管理仪表板通常有多个部分和子部分,每个部分都需要自己的菜单集。
TieredMenu提供了一个干净且组织良好的方式来表示这些菜单,使管理员能够轻松访问各种功能和设置。 -
多级下拉菜单:如果您需要实现多级下拉菜单,
TieredMenu简化了这一过程。它处理了管理嵌套菜单的复杂性,并确保在不同层次之间的平滑过渡。
为了说明 PrimeNG TieredMenu在电子商务环境中的应用,让我们考虑一个场景,其中我们有一个在线商店销售电子产品。我们希望创建一个导航菜单,允许用户浏览不同的产品类别和子类别。
要开始使用,我们需要从 PrimeNG 库中导入必要的模块:
import { TieredMenuModule } from 'primeng/tieredmenu'
之后,我们可以通过添加以下代码来启用 PrimeNG 的TieredMenu:
<p-tieredMenu [model]="tieredMenus" />
...
tieredMenus: MenuItem[] = [
{
label: 'Electronics',
icon: 'pi pi-tablet',
items: [
{
label: 'Computers',
icon: 'pi pi-desktop',
items: [
{ label: 'MacBook Air', icon: 'pi pi-apple' },
{ label: 'Ultrabooks', icon: 'pi pi-desktop' },
{ label: 'Mobile Workstations', icon: 'pi pi-mobile' },
],
},
...
],
},
]
让我们分解一下代码:
-
<p-tieredMenu [model]="tieredMenus" />:这代表 PrimeNG 的TieredMenu组件。model属性将组件类中的tieredMenus属性绑定到TieredMenu组件。 -
tieredMenus: MenuItem[]:这是一个来自 PrimeNG API 的MenuItem对象数组。每个MenuItem对象可以具有各种属性,例如label、icon、items、routerLink等。
让我们看看结果:
图 8.5 – 分层菜单
在这个例子中,我们有一个顶级菜单项 Electronics,它有几个子菜单:Computers、Smartphones 和 Tablets。每个子菜单都可以有自己的子菜单,从而创建一个层次结构。用户可以通过悬停在相应项上在菜单项和子菜单之间导航。
使用面包屑
PrimeNG Breadcrumb 是一个导航组件,它指示应用程序层次结构中的当前位置。它提供了一系列链接,每个链接代表层次结构中的一个级别,可以返回主页或主仪表板。
注意
应将面包屑用作辅助导航工具 – 它补充了主要导航,但不应该取代它。因此,请确保你的应用程序还有一个主要导航系统,例如菜单或侧边栏。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { BreadcrumbModule } from 'primeng/breadcrumb'
之后,我们可以通过添加以下代码来启用 PrimeNG Breadcrumb:
<p-breadcrumb [model]="breadcrumbItems" />
...
breadcrumbItems: MenuItem[] = [
{ icon: 'pi pi-home', routerLink: '/' },
{ label: 'Electronics', routerLink: '/electronics' },
{
label: 'Computers',
routerLink: '/electronics/computers',
},
{ label: 'MacBook Air', routerLink: '/electronics/computers/macbook-air' },
]
让我们分解代码并解释每个部分:
-
<p-breadcrumb [model]="breadcrumbItems" />:这代表了 PrimeNGBreadcrumb组件的实际用法。[model]属性用于将breadcrumbItems数组绑定到组件的模型属性。 -
breadcrumbItems: MenuItem[]:这是一个包含 PrimeNG API 中的MenuItem对象的数组。每个MenuItem对象可以具有各种属性,如label、icon、items、routerLink等。
让我们看看结果:
图 8.6 – 面包屑
在这个例子中,面包屑从 Home 链接开始,该链接将用户带回到网站的首页。随后的链接代表分类层次结构:Electronics、Computers,最后是当前页面,MacBook Air。
在深入研究了 PrimeNG 菜单的多种功能后,我们看到了它们如何简化导航并增强应用程序的用户体验。现在,让我们转向探索 PrimeNG 面板,这些是提供灵活方式在应用程序中组织和展示内容的必要组件。
介绍 PrimeNG 面板
Panel、ScrollPanel、Accordion、Splitter、Fieldset 和 TabView。
PrimeNG 面板可以在各种场景中使用,在这些场景中,内容组织和展示至关重要。以下是一些你可以从使用 PrimeNG 面板中受益的情况:
-
Accordion在你有多个内容部分并且想要通过只允许用户展开他们感兴趣的部分来节省空间时非常有用。 -
ScrollPanel组件使用户能够滚动内容,确保所有信息都保持可访问。 -
Splitter组件在你需要创建可调整大小和可折叠的面板时非常有价值,使用户能够根据他们的偏好自定义布局。 -
Fieldset组件在您有一个包含相关字段且需要视觉上分组在一起以改善用户体验和理解表单时特别有用。 -
TabView组件在您有多个相关信息或功能集可以组织到标签中时非常有用,允许用户轻松切换。
要开始,让我们创建一个基本的 PrimeNG 面板。
创建基本面板
PrimeNG 面板本质上是一个围绕内容包装的容器,为内容提供结构化的外观。它包含一个可选的标题栏,可以用来为内部内容提供标题或上下文。面板的美丽之处在于其简洁性。它不对内容施加任何特定的样式或行为;相反,它提供了一个整洁的边界,使内容更加突出。
无论您是在设计仪表板、表单还是内容页面,面板都可以成为您为内容提供结构的首选组件。当您想要将相关的信息片段组合在一起时,它尤其有用,这使用户更容易处理和理解。
注意
虽然 PrimeNG Panel功能多样,但使用它时必须谨慎。过度使用可能会使页面显得杂乱。始终追求设计功能和平衡。
让我们深入电子商务领域,看看 PrimeNG Panel的实际应用。在电子商务网站上,Panel组件可以用来显示关于产品的详细信息。例如,当用户点击产品缩略图或名称时,面板可以滑动或展开以显示产品详情,包括图片、描述、规格和客户评价。这使用户能够在不离开当前页面的情况下探索产品信息。
要开始,我们需要从 PrimeNG 库中导入必要的模块:
import { PanelModule } from 'primeng/panel'
一旦安装并导入依赖项,让我们看看如何设置 PrimeNG 面板:
<p-panel header="Product Details" [toggleable]="true">
<p>
Experience the power of Laptop XYZ, featuring the latest processor and a
sleek design.
</p>
<!-- other information -->
</p-panel>
让我们分解代码并解释每个部分:
-
<p-panel>:这是在 PrimeNG 中创建面板的主要组件标签。 -
header="Product Details":此属性将面板的标题或头部设置为"Product Details"。 -
-toggleable]="true":此属性使面板的内容可折叠。当设置为true时,允许用户点击面板标题来切换(显示/隐藏)面板内的内容。
让我们看看结果:
图 8.7 – 基本面板
在这个例子中,您可以通过点击减号或加号图标来展开或折叠产品详情。
与 ScrollPanel 一起工作
PrimeNG ScrollPanel 允许你在应用程序内创建可滚动的区域,使用户能够查看超出可用空间的内容。ScrollPanel 组件提供类似原生的滚动体验,这意味着当用户在应用程序中导航时,滚动感觉平滑自然,就像在设备内置的应用程序中一样,该组件还支持水平和垂直滚动。
与在不同平台上可能不一致的默认浏览器滚动条不同,ScrollPanel 提供了一致的视觉和感觉。这不仅仅是关于美观;这是为了为用户提供更平滑、更直观的滚动体验。
让我们通过添加 ScrollPanel 来改进 图 8.7 中显示的基本面板。首先,从 PrimeNG 库中导入必要的模块:
import { ScrollPanelModule } from 'primeng/scrollpanel'
现在,让我们看看如何设置 PrimeNG ScrollPanel:
<p-panel header="Product Details" [toggleable]="true">
<p-scrollPanel [style]="{ width: '100%', height: '200px' }">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ut...
</p>
<!-- Other content -->
</p-scrollPanel>
</p-panel>
让我们分解代码并解释其功能:
-
<p-panel ...>:这代表 PrimeNGPanel组件。 -
<p-scrollPanel [style]="{ width: '100%', height: '200px' }">:这将在面板内创建一个可滚动的视口来处理溢出的内容。它允许用户垂直滚动内容。[style]属性用于定义可滚动区域的尺寸。在这种情况下,宽度设置为100%,高度设置为200px。
让我们看看结果:
图 8.8 – 带滚动条的 ScrollPanel
在这个例子中,我们在一个具有固定宽度和高度的基面板内定义了 ScrollPanel。由于 产品详情 面板的内容相当大,滚动功能允许用户轻松查看内容,而不会失去整个页面的上下文。
与 Accordion 一起工作
PrimeNG Accordion 是一个 UI 组件,允许你以堆叠的方式显示内容。可以将其视为可展开/折叠的面板垂直堆栈。每个面板都有一个标题栏,当你点击它时,面板内的内容展开,显示更多详细信息。这种机制确保用户不会一次性被过多信息淹没。相反,他们可以选择深入哪些部分,使他们的浏览体验更加专注和整洁。
在空间有限且需要展示与相关详细内容关联的项目列表的情况下,Accordions 非常有用。它们特别适用于以下情况:
-
组织相关内容:将相关部分或主题分组,使用户能够快速导航到他们感兴趣的区域
-
多步骤表单:将长表单分解成可管理的部分,逐步引导用户
-
常见问题解答:展示一系列问题,并展开以显示答案
-
产品规格:在电子商务中,使用手风琴式布局显示产品的详细规格或特性,而不会让用户感到信息过载
想象一下,您正在开发一个销售电子小工具的电子商务平台。对于每个产品,都有大量信息需要传达规格、用户评价、保修详情等。使用 PrimeNG 手风琴,您可以整洁地组织这些信息。
要开始使用,请从 PrimeNG 库中导入必要的模块:
import { AccordionModule } from 'primeng/accordion'
现在,我们可以看到如何设置 PrimeNG 手风琴:
<p-accordion>
<p-accordionTab header="Specifications">
<ul>
<li>Processor: XYZ</li>
<li>Memory: 8GB RAM</li>
<!-- ... other specs ... -->
</ul>
</p-accordionTab>
<p-accordionTab header="User Reviews">
<p>"This product is fantastic! Highly recommend." - Alex G</p>
<!-- ... other reviews ... -->
</p-accordionTab>
<p-accordionTab header="Warranty">
<p>This product comes with a 2-year warranty covering...</p>
</p-accordionTab>
<!-- ... other tabs ... -->
</p-accordion>
提供的代码演示了如何使用 PrimeNG Accordion 组件创建一组具有不同内容部分的标签。让我们分解它:
-
<p-accordion>...</p-accordion>:此代码片段将Accordion组件包裹在其子元素周围,表示手风琴部分的开始和结束。 -
<p-accordionTab header="...">:此元素代表手风琴的一个部分。header 属性定义了该部分的标题。
让我们看看结果:
图 8.9 – 手风琴
我们创建了三个手风琴标签,因此当用户点击标题时,标签内的相关内容会展开。
与 Fieldset 一起工作
PrimeNG Fieldset 是一个容器组件,旨在将相关内容分组在一个视觉上独特的边界内。它与经典的 HTML <fieldset> 元素类似,但增加了额外的功能和样式。最显著的功能是其可选的可切换属性,允许用户展开或折叠内容,使其非常适合需要隐藏/显示功能的章节。
Fieldset 是您在以下情况下首选的组件:
-
分组相关元素:这在表单中尤其如此,您可能希望将相关的输入字段分组
-
提高可读性:通过分割内容,您使用户更容易处理信息
-
交互式内容展示:利用其可切换功能,您可以在不压倒主要内容的情况下展示可选或补充信息
在上一节中,我们使用 PrimeNG Accordion(如图 图 8.9 所示)显示了产品信息,如规格、保修详情和用户评价。除了使用 Accordion,我们还可以使用 Fieldset 来整洁地包装每个部分。
要开始使用,请从 PrimeNG 库中导入必要的模块:
import { FieldsetModule } from 'primeng/fieldset'
然后,让我们设置 PrimeNG Fieldset:
<p-fieldset legend="Specifications" [toggleable]="true" class="block mb-4">
<ul>
<li>Screen Size: 15.6 inches</li>
<li>Processor: Intel i7</li>
<li>RAM: 16GB</li>
<!-- ... other specifications ... -->
</ul>
</p-fieldset>
<p-fieldset legend="User Reviews" [toggleable]="true" class="block mb-4">
<p>"Fantastic product with great performance!" - Yen N</p>
<!-- ... other reviews ... -->
</p-fieldset>
<p-fieldset
legend="Warranty Details"
[toggleable]="true"
class="block mb-4"
>
<p>
This product comes with a 2-year warranty covering manufacturing
defects.
<!-- ... more warranty details ... -->
</p>
</p-fieldset>
提供的代码演示了如何使用 PrimeNG Fieldset 组件及其特定属性。让我们分解代码并解释每个部分:
-
<p-fieldset>:代表 PrimeNGFieldset组件的 HTML 标签。 -
legend="规格":legend属性设置Fieldset组件的标题或描述。在这种情况下,legend设置为规格,表示Fieldset组件内的内容与产品的规格相关。 -
[toggleable]="true":[toggleable]属性是一个属性绑定,它启用了Fieldset组件的可切换功能。当设置为true时,字段集中的内容可以被用户展开或折叠。这使用户能够根据需要隐藏或显示规格部分。
让我们看看结果:
图 8.10 – 字段集
在这个例子中,每个字段集都作为特定类型信息的容器。用户可以快速浏览图例(如规格或用户评论)并决定他们想要深入了解哪些部分,并根据需要展开它们。
使用 TabView
PrimeNG 的TabView是一个导航组件,允许您将内容分解成多个标签显示。每个标签都作为其独特内容的容器,确保信息是有组织的且易于访问。使用TabView,用户可以快速在不同部分之间切换,而不会感到不知所措。
TabView功能丰富,在各种场景中都有其位置:
-
设置或配置页面:这样可以将不同类别的设置分组到单独的标签下
-
个人资料页面:这可能是在您想要将用户信息、活动历史和设置分别放入不同的标签时
-
电子商务中的产品描述:这是当您想要将产品详情、客户评论和规格分开时
-
文档:这是当您想要将指南、API 参考和示例分开时
在前面的章节中,我们使用 PrimeNG 的Accordion(图 8.9)和Fieldset(图 8.10)显示了产品信息。现在,让我们尝试使用TabView。要开始,请从 PrimeNG 库中导入必要的模块:
import { TabViewModule } from 'primeng/tabview'
现在让我们看看如何设置 PrimeNG 的TabView:
<p-tabView>
<p-tabPanel header="Warranty">
<p>
This product comes with a 2-year warranty covering manufacturing
defects.
<!-- ... more warranty details ... -->
</p>
</p-tabPanel>
<p-tabPanel header="Specifications">
<ul>
<li>Screen Size: 15.6 inches</li>
<li>Processor: Intel i7</li>
<li>RAM: 16GB</li>
<!-- ... other specifications ... -->
</ul>
</p-tabPanel>
<p-tabPanel header="Reviews">
<p>"Spectacular product! Highly recommended" - Aaron D</p>
<!-- ... other reviews ... -->
</p-tabPanel>
</p-tabView>
让我们分解代码并解释每个部分:
-
<p-tabView>:这个 PrimeNG 组件作为我们标签的容器。 -
<p-tabPanel header="Warranty">:这些组件代表tabView容器内产品信息的不同部分。header属性包含标签的值。
让我们看看结果:
图 8.11 – TabView
通过使用 PrimeNG 的TabView,我们可以创建内容的不同部分,这些部分以标签的形式显示。用户可以通过点击标签标题(保修、规格或评论)在相应的部分之间切换,并访问相关信息。
使用 Splitter
PrimeNG 的Splitter是一个布局组件,允许用户通过拖动分隔线来调整其子元素的大小。将其想象为用户可以根据他们的查看偏好调整大小的可调整分区。它在需要提供两个或更多内容部分之间可调整比例的场景中特别有用,无论是水平还是垂直。
Splitter组件在各种场景中都非常出色:
-
当你有多个小部件或面板,并希望给用户提供调整它们大小的灵活性时,使用
Splitter -
当你可能在一侧有一个代码部分而在另一侧有一个预览时,可以使用
Splitter组件 -
Splitter组件允许用户调整视图以并排比较两个图像 -
Splitter组件可用于需要提供可调整的多面板视图的应用程序
让我们考虑一个例子,其中 PrimeNG 的Splitter组件将两个图像并排比较。首先,从 PrimeNG 库中导入必要的模块:
import { SplitterModule } from 'primeng/splitter'
然后让我们看看如何设置 PrimeNG 的Splitter组件:
<p-splitter [style]="{ height: '300px' }" layout="horizontal">
<ng-template pTemplate>
<div class="col flex align-items-center justify-content-center">
<img src="img/placeholder.png" alt="Image 1" />
</div>
</ng-template>
<ng-template pTemplate>
<div class="col flex align-items-center justify-content-center">
<img src="img/placeholder.png" alt="Image 2" />
</div>
</ng-template>
</p-splitter>
让我们分解代码并解释每个部分:
-
<p-splitter>:这代表 PrimeNG 的Splitter组件。 -
[style]="{ height: '300px' }":这用于将内联 CSS 样式应用到Splitter组件上。在这种情况下,Splitter组件的高度通过height属性设置为 300 px。 -
layout="horizontal":layout属性定义了Splitter组件内面板的排列方向。在这个例子中,它被设置为horizontal,表示面板将以水平方式并排显示。 -
<ng-template pTemplate>:pTemplate指令是 PrimeNG 特有的,用于标记 Angular 模板为 PrimeNG 模板。
让我们看看结果:
图 8.12 – Splitter
在这里,我们在Splitter组件内部创建了两个面板,每个面板包含一个用于比较目的的图像。
在探索了 PrimeNG 面板的各种功能和能力之后,我们获得了宝贵的见解,了解了这个强大的组件如何增强 Angular 应用程序中内容的布局和展示。
摘要
在本章中,我们穿越了 PrimeNG 组件的广阔世界。它带我们经历了一次导航和布局组件的复杂旅程。这些元素是任何应用程序的骨架,决定了用户如何与内容互动,并确保无缝体验。
我们深入研究了从菜单和面板的各种组件。每个组件都服务于独特的目的,从组织内容到增强导航。到目前为止,你应该已经牢固地掌握了在应用程序中何时以及如何使用这些组件。这些组件将使我们能够以有意义的方式构建和展示内容,从而提高整体用户体验。此外,通过各种示例,我们看到了这些组件如何集成到实际应用中。这些实用见解旨在弥合理论知识与实际实施之间的差距。
随着我们过渡到下一章,我们将深入探讨使用主题定制 PrimeNG 组件的艺术。主题化是一个强大的工具,它允许你根据品牌指南或特定的设计偏好定制组件的外观和感觉。我们将探讨如何利用主题化的力量,使 PrimeNG 组件真正成为你自己的。所以,准备好开始一段丰富多彩的定制和设计之旅吧!
第三部分:高级技术和最佳实践
在本部分,你将深入了解与 PrimeNG 一起工作的高级技术和最佳实践。你将探索定制、优化、重用、国际化以及测试策略,以增强你的 PrimeNG 驱动的 Angular 应用程序。
在本部分的结尾,你将深入理解这些高级主题,并具备构建稳健、高效和用户友好的应用程序的宝贵技能。
本部分包含以下章节:
-
第九章, 使用主题定制 PrimeNG 组件
-
第十章, 探索 Angular 应用程序的优化技术
-
第十一章, 创建可重用和可扩展的组件
-
第十二章, 处理国际化和本地化
-
第十三章, 测试 PrimeNG 组件
第九章:使用主题定制 PrimeNG 组件
每个应用程序都有自己的独特身份,其视觉吸引力在定义该身份方面发挥着重要作用。虽然功能至关重要,但应用程序的外观和感觉可以显著影响用户体验。PrimeNG 提供了一个强大的主题系统,允许您定制组件的外观,确保应用程序不仅运行良好,而且看起来也符合要求。
在本章中,您将探索使用主题在 Angular 应用程序中定制 PrimeNG 组件外观的过程。通过掌握这些技术,您将能够根据应用程序的独特品牌和设计要求定制 PrimeNG 组件的视觉表现。
我们还将深入探讨各种主题,如使用预构建主题、创建自定义主题、利用主题设计工具以及覆盖组件样式。您将发现 PrimeNG 主题的强大和灵活性,并学习如何实现统一且个性化的用户界面。
本章将涵盖以下主题:
-
介绍 PrimeNG 主题
-
使用预构建主题
-
创建您自己的自定义主题
-
覆盖组件样式和其他技巧
技术要求
本章包含有关 PrimeNG 主题的各种工作代码示例。您可以在以下 GitHub 仓库的chapter-09文件夹中找到相关源代码:github.com/PacktPublishing/Next-Level-UI-Development-with-PrimeNG/tree/main/apps/chapter-09。
介绍 PrimeNG 主题
主题在创建视觉吸引力和一致的用户界面中起着至关重要的作用,允许您根据应用程序的品牌和设计要求自定义组件的外观。PrimeNG 提供了一个全面的主题系统,使您能够创建个性化的统一用户界面。
虽然 PrimeNG 主题不仅仅是改变颜色或字体,但它涉及修改组件外观的各个方面,如颜色、字体、间距和其他设计元素。PrimeNG 提供了一系列的工具、资源和指南,以简化主题过程,使开发者能够创建独特且视觉上吸引人的用户界面。
根据应用程序的具体要求,PrimeNG 主题被用于各种场景。以下是一些 PrimeNG 主题证明非常有价值的使用案例:
-
品牌和定制:当您需要将 PrimeNG 组件的外观与您应用程序的品牌指南保持一致时,主题允许您创建一致且个性化的外观和感觉。
-
应用特定设计:在某些情况下,PrimeNG 组件的默认样式可能不符合您应用程序特定的设计要求。主题化使您能够修改组件的外观,以匹配您应用程序的视觉设计语言,确保用户界面的一致性和和谐。
-
一致的样式:在构建由多个开发者或团队参与的大型应用程序时,主题化确保了不同组件之间的视觉样式一致性。通过遵循统一的主题化方法,您可以在整个应用程序中保持一致的用户体验。
在掌握了 PrimeNG 主题的基础知识后,是时候深入了解实际方面了。快速启动主题之旅的最快方法之一是利用 PrimeNG 丰富的预建主题,我们将在下一节中探讨。
使用预建主题
PrimeNG 预建主题是一系列预定义的样式表,定义了 PrimeNG 组件的视觉外观。这些主题基于流行的设计框架,如 Bootstrap 和 Material Design,并附带一系列颜色方案和变体。每个主题都为所有 PrimeNG 组件提供一致的样式,确保您的应用程序具有一致和精致的外观。
预建主题作为 npm 分发的一部分随 PrimeNG 一起提供,易于导入,并且可以通过几个简单的步骤应用到您的应用程序中。这些主题也高度可定制,允许您根据项目需求调整颜色、字体和其他视觉属性。
何时使用 PrimeNG 预建主题
虽然定制化提供了独特的身份,但在某些情况下,预建主题确实可以挽救局面:
-
快速原型设计:当您处于应用程序开发的初期阶段,需要快速设计来可视化功能时
-
一致的设计语言:对于需要跨多个应用程序或模块保持一致设计的项目
-
减少开发时间:当项目时间表紧张,没有时间进行广泛的设计迭代时
PrimeNG 预建主题示例
在前面的章节中,我们有机会使用 PrimeNG 主题。在本章中,让我们回顾一下如何将 PrimeNG 主题集成到我们的 Angular 应用程序中。
要使用预建主题,只需将其导入到您的项目中即可。让我们看看如何:
-
导航到 PrimeNG 内置主题(
primeng.org/theming#builtinthemes),并选择与您的项目氛围产生共鸣的主题。 -
一旦您选择了主题,将其集成到您的项目中。例如,如果您选择了
lara-light-blue主题,请将以下行添加到styles.scss或styles.css://styles.scss @import 'primeng/resources/themes/lara-light-blue/theme.css'; @import 'primeng/resources/primeng.css';这个导入语句确保了
lara-light-blue主题中定义的样式被应用到你的应用程序中。一旦主题被导入,所有 PrimeNG 组件将自动采用主题定义的样式。 -
接下来,你可以在应用程序中使用 PrimeNG 组件,例如
p-button、p-card和p-table组件。这些组件将继承预构建主题定义的样式,使它们具有一致且视觉上吸引人的外观。
注意
你的应用程序可能有自定义字体或样式。始终确保主题的 CSS 在默认 PrimeNG CSS 之后加载,以确保主题样式具有优先权。
我们已经探讨了 PrimeNG 预构建主题的便利性,它们提供了大量视觉上吸引人的样式。现在,让我们深入探讨切换主题的话题,我们将学习如何无缝地在不同的 PrimeNG 主题之间切换,以满足我们应用程序的设计需求和偏好。
切换主题
PrimeNG 预构建主题的一个关键优势是你可以即时切换到不同的主题。这个特性允许你的应用程序用户选择他们偏好的主题,为他们提供个性化的可定制体验。
要切换主题,通常需要替换项目中主题 CSS 文件的引用。例如,如果你目前使用的是 lara-blue-light 主题,并希望切换到 bootstrap4-light-purple 主题,你将在 index.html 文件中替换 CSS 文件引用。
这里是如何一步步操作的指南:
- 为了切换主题,你需要将所有主题准备在
assets文件夹中。你可以在node_modules/primeng/resources/themes文件夹下找到内置 PrimeNG 主题的完整列表:
图 9.1 – PrimeNG 内置主题
之后,你可以将你想要在应用程序中使用的主题复制到你的 assets 文件夹中:
图 9.2 – 复制的内置主题
在这个例子中,我将四个内置主题复制到我们的应用程序中:bootstrap4-light-blue、lara-light-blue、md-dark-indigo 和 viva-dark。
-
将你的默认主题引用添加到
index.html文件中。因此,你将不再在style.scss文件中设置默认值,而是在index.html文件中设置:<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>chapter-09</title> <base href="/" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" type="image/x-icon" href="favicon.ico" /> <link id="theme-link" rel="stylesheet" type="text/css" href="assets/lara-light-blue/theme.css" /> </head> <body> <primengbook-root /> </body> </html>在这段代码中,我们添加了对
lara-light-blue主题的theme-linkID 的引用。 -
现在,是时候给我们的组件添加切换主题的功能了。以下是代码:
<div class="flex align-items-center" *ngFor="let theme of themes"> <p-radioButton [name]="theme.name" [value]="theme.value" [(ngModel)]="selectedTheme" inputId="{{ theme.value }}" (onClick)="changeTheme()" /> <label for="{{ theme.value }}" class="ml-2">{{ theme.name }}</label> </div> ... themes = [ { name: 'Lara Light Blue', value: 'lara-light-blue' }, { name: 'Bootstrap4 Light Purple', value: 'bootstrap4-light-purple' }, { name: 'Viva Dark', value: 'viva-dark' }, { name: 'Material Dark Indigo', value: 'md-dark-indigo' }, ] selectedTheme = 'lara-light-blue' changeTheme() { const themeLink = document.getElementById('theme-link') themeLink?.setAttribute('href', `assets/${this.selectedTheme}/theme.css`) }让我们分解一下代码:
-
<div class="flex align-items-center" *ngFor="let theme of themes">: 这段代码使用ngFor指令遍历themes数组。对于数组中的每个主题,它使用p-radioButton组件创建一个单选按钮输入。 -
themes = [...]:这定义了themes数组,它包含代表不同主题的对象。每个主题对象都有一个name属性,表示主题的显示名称,以及一个value属性,表示主题的唯一标识符。 -
selectedTheme:这表示最初选择的主题值。 -
changeTheme() {...}:当点击单选按钮时调用此方法。它检索具有theme-linkID 的link元素。之后,它将link元素的href属性更新为指向所选主题的 CSS 文件。
-
让我们看看结果:
图 9.3 – 切换主题
我们已经设置了一个主题切换器,允许用户使用单选按钮选择主题。当点击单选按钮时,我们将能够切换到所需的主题。您可以看到,在左侧我们正在使用 Lara Light Blue 主题,而在右侧,我们正在使用 Bootstrap4 Light Purple,这将给我们的用户带来不同的体验。
通常,在 PrimeNG 中使用预构建主题为您提供了方便且高效的方式来设计应用程序。在下一节中,我们将探讨在 PrimeNG 中创建自定义主题的过程,让您能够打造真正个性化且独特的用户体验。
创建您自己的自定义主题
虽然 PrimeNG 提供了大量的预构建主题,但可能存在一些情况,您希望拥有一个独特的外观和感觉,更紧密地与您的品牌或特定的设计要求相匹配。这就是自定义主题发挥作用的地方。这些主题允许您根据您的确切规格定制 PrimeNG 组件的外观。
什么是 PrimeNG 自定义主题?
PrimeNG 中的自定义主题本质上是一组 CSS 样式,它覆盖了 PrimeNG 组件的默认样式。通过创建自定义主题,您有灵活性来定义颜色、字体、间距和其他设计元素,这些元素与您的品牌身份或项目的特定设计语言相匹配。
何时使用 PrimeNG 自定义主题?
自定义主题在以下情况下特别有益:
-
您正在构建一个品牌应用程序,其视觉身份需要与其他品牌数字资产保持一致
-
预构建主题与您项目的特定设计要求不匹配
-
您的目标是创建一个独特的用户界面,使其与众不同于典型应用
-
需要遵守特定的可访问性指南,这些指南可能不在默认主题中涵盖
如何创建 PrimeNG 自定义主题
创建 PrimeNG 自定义主题可能听起来有些令人畏惧,但有了 PrimeNG 的结构,它相当简单。您有三个选择,每个选择都提供其自身的优点和灵活性。让我们深入了解每个选项:
-
视觉编辑器:视觉编辑器是 PrimeNG 提供的一个用户友好的工具,允许您直观地自定义和设计您的主题
-
命令行 Sass 编译:如果你更喜欢更手动的方法,你可以选择使用命令行 Sass 工具来编译你的主题
-
在项目中嵌入 SCSS 文件:第三种选择是将 SCSS 文件直接嵌入到你的项目目录结构中
注意
截至本书发布时,视觉编辑器目前处于禁用状态。然而,有一个好消息——PrimeTek 团队已经决定开源设计师,使其免费可用。这一激动人心的开发的预期发布时间定于 2024 年第一季度。有关最新信息,请访问官方 PrimeTek 网站。
在所有三种选项中,将生成的主题文件导入到你的项目中至关重要。这确保了自定义主题被正确应用于 PrimeNG 组件,让你能够享受到个性化视觉风格的好处。
选择与你的偏好和项目要求最匹配的选项,开始为你的 PrimeNG 应用程序创建独特且视觉吸引人的主题之旅。
通过视觉编辑器创建自定义主题
PrimeNG 的主题世界随着视觉编辑器的引入而发生了革命性的变化。你再也不需要深入到 Sass 或 CSS 的代码行中去,以获得组件的完美外观。使用视觉编辑器,创建一个自定义主题就像拖动滑块或从调色板中选择颜色一样直观。
通过其直观的界面,你可以修改主题的各个方面,如颜色、字体、间距等。视觉编辑器提供实时预览,使你在自定义主题时能够轻松看到变化。一旦你对修改满意,你可以导出主题文件,该文件可以直接导入到你的项目中。
使用视觉编辑器创建自定义主题非常简单。以下是一个逐步指南:
-
导航到 PrimeNG 主题页面并启动视觉编辑器。
-
从与你期望的外观最接近的预构建主题开始。这为你提供了一个基础,你可以在此基础上进行进一步的定制。在这个例子中,我将选择
lara-light主题。
图 9.4 – 选择基本主题
- 使用视觉编辑器的直观控件来调整颜色、字体和其他设计元素。随着你的更改,你将看到组件的实时预览。
图 9.5 – 定制你的主题
在左侧面板中,你可以修改基本主题。有许多选项供你自定义。
注意
在撰写本书时,当前的视觉编辑器被认为处于遗留状态。一个基于新先进 UI 的 Theme Designer 将很快发布。
- 一旦你对自定义主题满意,只需导出它即可。视觉编辑器将为你生成所有必要的 CSS 文件。
图 9.6 – 下载您的自定义主题
在完成自定义后,您可以通过点击名为Download的文件夹来开始下载您的自定义主题theme.css。
-
下载导出的文件后,您可以将它们包含到您的 Angular 项目中。请确保它们在默认 PrimeNG 样式之后加载,以确保您的自定义设置优先。
如果您的应用程序中只有一个主题,您可以直接将其放入
styles.scss文件或index.html中:// styles.scss @import 'assets/my-awesome-theme/theme.css';
这里是结果:
图 9.7 – 应用您的自定义主题
现在,您的应用程序已经具有了您自定义主题的期望外观和感觉。
通过 Sass 编译创建自定义主题
第二种方法,使用 Sass 编译,让您完全控制主题自定义过程。您可以手动编辑主题的 SCSS 文件,调整变量以实现所需的视觉风格。一旦您进行了必要的修改,您可以使用命令行 Sass 编译器生成 CSS 输出。然后,可以将编译后的 CSS 文件导入到您的项目中,确保您的自定义主题应用于 PrimeNG 组件。
这里是如何操作的:
-
从 GitHub 克隆
primeng-sass-theme仓库:git clone https://github.com/primefaces/primeng-sass-theme.git -
安装 NPM 包:
cd primeng-sass-theme npm install -
在安装必要的包后,我们可以在
themes|mytheme目录下找到所有的 SCSS 文件:
图 9.8 – mytheme 文件夹
在mytheme文件夹下,您有几个选项来自定义您的自定义主题:
-
variables:您可以在该文件夹下自定义 CSS 变量,更改按钮背景、主要文本颜色、边框半径等 -
_extension.scss:如果您想覆盖组件设计,请更新此文件 -
_font.scss:这是您可以定义项目自定义字体的地方 -
theme.scss:此文件导入主题文件,以及theme-base文件夹,以便将所有内容合并
-
在对您的自定义主题进行更改后,通过运行以下命令来编译您的更改:
sass --update themes/mytheme/theme.scss:themes/mytheme/theme.css [2023-09-17 14:33:46] Compiled themes/mytheme/theme.scss to themes/mytheme/theme.css.
您可以看到,在编译后,我们在mytheme文件夹下创建了一个theme.css文件,现在可以将其添加到我们的项目中。
通过嵌入 SCSS 文件创建自定义主题
这种第三种方法允许您将主题自定义无缝集成到现有的构建环境中。通过将主题 SCSS 文件放置在项目中的指定位置,例如assets或styles文件夹,您可以在构建过程中利用您的构建工具自动将 SCSS 文件编译成 CSS。
这里是步骤:
- 将
mytheme和theme-base文件夹复制到我们的assets文件夹。此选项使您能够结合 Angular CLI 默认流程。
图 9.9 – Angular 项目中的 mytheme
-
然后,我们只需要从
mytheme导入theme.scss到styles.scss:@import 'assets/mytheme/theme.scss'; -
最后,当我们修改
mytheme下的任何内容时,Angular CLI 会为我们自然地处理编译,无需任何手动工作。
在掌握 PrimeNG 主题化的旅程中,我们看到了创建自定义主题方法的强大功能和灵活性,使主题定制变得简单且愉快。现在,让我们将重点转移到覆盖组件样式和其他高级样式技术,以真正使我们的 UI 独具特色。
覆盖组件样式和其他技巧
虽然 PrimeNG 提供了大量的主题和定制选项,但总会有一些场景需要我们调整某些样式以适应我们应用程序的独特需求。本节将指导您通过覆盖组件样式的流程,并分享一些额外的技巧和窍门来增强您的主题体验。
如何覆盖组件样式
在 PrimeNG 中覆盖组件样式与样式任何其他 Angular 组件类似。关键是理解您想要样式的组件的结构并使用特定的 CSS 选择器。以下是我们的做法:
- 检查组件:在您覆盖样式之前,您需要知道您正在针对什么。使用您浏览器的开发者工具检查组件并了解其结构。以下是检查浏览器的一个示例:
图 9.10 – 浏览器检查示例
在提供的屏幕截图中,您可以观察到位于左侧的 Panels 菜单的详细 HTML 元素结构。
-
p-menuitem-link-active类,允许您选择性地应用 CSS 样式到它上。 -
styles.scss以将样式应用到您的组件上。例如,为了给活动的路由链接添加下划线,您可以在style.scss中添加以下 CSS:.p-menu .p-menuitem-link.p-menuitem-link-active { text-decoration: underline; } -
::ng-deep伪类确保样式渗透到子组件中。这在尝试样式化 PrimeNG 组件的内部部分时特别有用。以下是一个示例::host ::ng-deep my-component .p-button { background-color: #333; color: #fff; }在此示例中,我们可以在我们的组件中覆盖 PrimeNG 按钮的样式,这使得定位和维护变得更加容易。这些更改仅将不同的颜色和背景颜色应用到我们的按钮上,使其与您的应用程序中的其他按钮区分开来。
注意
Angular 团队决定在 Angular 的未来版本中弃用 ::ng-deep,因此请谨慎使用。您可以在 angular.io/guide/component-styles#deprecated-deep--and-ng-deep 找到更多相关信息。
注意
避免使用 !important。虽然使用 !important 来强制样式可能很有吸引力,但我们应避免这种做法。它会使未来的更改变得困难,并可能导致不可预测的结果。
使用 PrimeNG 公共工具
PrimeNG Utils 是 PrimeNG 提供的一组实用类,用于帮助您完成常见的样式任务。这些实用类提供了一种快速将特定样式或行为应用于元素的方法,而无需编写自定义 CSS。以下是一些 PrimeNG utils 的简要概述:
图 9.11 – 常见的 PrimeNG 工具类
使用 PrimeNG CSS 变量
在现代网络开发中,CSS 变量(也称为 CSS 自定义属性)已成为创建更灵活和可维护的样式表的有力工具。PrimeNG 通过提供一组定义颜色的 CSS 变量来利用这种力量,这使得您更容易自定义应用程序的主题。
PrimeNG 的颜色系统是基于一组预定义的 CSS 变量构建的。这些变量代表了一系列颜色,从主色和辅助色到各种色调和色调。通过利用这些变量,您可以在整个应用程序中确保颜色使用的统一性,并轻松地根据需要调整外观。
例如,PrimeNG 定义了如 --primary-color 这样的主颜色以及如 --primary-color-text 这样的主颜色文本。这只是冰山一角,因为还有用于文本颜色、表面和突出显示等变量的变量。
注意
有关颜色变量的完整列表,请访问 primeng.org/colors。
使用这些颜色变量很简单。您不需要在样式表中硬编码颜色值,而是引用 PrimeNG 颜色变量。这不仅确保了一致性,还使得未来的颜色更改变得容易。
以下是一个简单的示例:
.my-custom-button {
background-color: var(--primary-color);
border-radius: var(--border-radius);
}
在代码中,按钮的背景颜色设置为 PrimeNG 的 --primary-color,边框半径设置为 --border-radius。如果您将来决定更改主颜色或边框半径,按钮的外观将自动更新,无需修改 .my-custom-button 样式。
自定义 PrimeNG 颜色变量
CSS 变量的一个主要优点是它们可以被覆盖。如果您希望自定义 PrimeNG 提供的默认颜色,您可以通过在样式表中重新定义变量轻松地做到这一点。
例如,以下是更改主颜色的方法:
// styles.scss
:root {
--primary-color: #3498db; /* Your desired color */
}
通过在根级别设置,您实际上更改了所有使用 --primary-color 变量的组件和元素的主颜色。
其他技巧和窍门
在本节中,我们将了解一些有价值的技巧、技术和最佳实践,这些将在使用主题时非常有帮助:
-
全局样式:如果您想在应用程序中全局应用样式,您可以在全局 CSS 文件中定义它们,并将其包含在您的应用程序中。这样,您可以自定义诸如排版、颜色和布局等常见元素。
-
保持更新:PrimeNG 正在积极开发。新版本可能会引入变化。始终检查文档并相应地更新你的样式。
-
使用基础主题:在开始一个新项目时,考虑使用预构建的主题作为基础。它为你提供了一个坚实的基础,然后你可以根据需要覆盖特定的部分。你可以查看内置主题的列表:
primeng.org/theming#builtinthemes。 -
theme-base:.p-button { ... &:enabled:hover { ... border-color: $buttonHoverBorderColor; } }从代码中,你可以看到当按钮被悬停时,按钮使用了
$buttonHoverBorderColor变量来设置边框颜色。这个变量在mytheme下的variables/_button.scss中声明:/// Border color of a button in hover state /// @group button $buttonHoverBorderColor: $primaryDarkColor;当在
_button.scss中更新$buttonHoverBorderColor的值时,它将反映在所有使用此$buttonHoverBorderColor变量的组件中,例如按钮悬停状态。
注意
提供的按钮组件变量示例只是一个小子集。更多信息和与按钮相关的完整代码,你可以查看以下链接:github.com/primefaces/primeng-sass-theme/blob/main/theme-base/components/button/_button.scss 和 github.com/primefaces/primeng-sass-theme/blob/main/themes/mytheme/variables/_button.scss。
- 跨浏览器测试:始终在不同的浏览器中测试你的样式以确保一致性。某些组件可能有浏览器特定的样式。
简而言之,最重要的是要跟上 PrimeNG 和 Angular 团队的变化。如果我们能利用最新的实践来改进我们的应用程序,这将是有益的。现在,让我们总结本章涵盖的关键点,并反思重要的收获。
摘要
在本章中,我们深入探讨了 PrimeNG 主题的世界,从理解 PrimeNG 主题的基础到掌握定制组件以适应我们独特需求的艺术。
我们首先介绍了 PrimeNG 主题的概念,强调了它在创建统一且视觉上吸引人的 Angular 应用程序中的重要性。通过利用 PrimeNG 的主题功能,我们可以确保应用程序的一致外观和感觉,从而提升用户体验。
我们随后探索了 PrimeNG 提供的丰富多样的预构建主题。这些主题从浅色到深色,应有尽有,提供了一种快速简单的方式,让我们的应用程序看起来专业,无需进行大量定制。在预构建选项之外,我们学习了如何使用可视化编辑器创建自己的自定义主题。这个强大的工具允许我们调整应用程序外观的每一个细节,确保它与我们的品牌或期望的美学完美契合。
随着我们不断进步,我们讨论了覆盖组件样式和 PrimeNG 提供的实用类的重要性。这些工具为我们提供了调整应用程序外观的灵活性,确保每一个细节都恰到好处。主题化不仅仅是让应用程序“看起来漂亮”。它关乎创造一个一致、直观且引人入胜的用户体验。通过理解和有效利用 PrimeNG 的主题化功能,我们可以打造出不仅外观惊艳,而且能与目标受众产生共鸣的应用程序。这种知识使我们能够提升我们的应用程序,在竞争激烈的市场中脱颖而出。
随着我们过渡到下一章节,我们将把焦点转向性能优化技术。在这里,我们将揭示确保我们的 Angular 应用程序运行顺畅和高效的战略和最佳实践。在主题化的基础现在稳固地掌握在我们手中后,我们准备好应对性能和可扩展性的复杂性。