Web 应用程序开发教程 - 第 2 部分:书籍列表页面
本地化
在开始 UI 开发之前,我们首先需要准备本地化文本(通常是在开发应用程序时按需进行)。
本地化文本位于 Acme.BookStore.Domain.Shared 项目的 Localization/BookStore 文件夹下:
打开 en.json 文件(英文翻译),并按以下内容修改:
{
"Culture": "en",
"Texts": {
"Menu:Home": "首页",
"Welcome": "欢迎",
"LongWelcomeMessage": "欢迎使用本应用程序。这是一个基于 ABP 的启动项目。更多信息请访问 abp.io。",
"Menu:BookStore": "书店",
"Menu:Books": "书籍",
"Actions": "操作",
"Close": "关闭",
"Delete": "删除",
"Edit": "编辑",
"PublishDate": "出版日期",
"NewBook": "新书",
"Name": "名称",
"Type": "类型",
"Price": "价格",
"CreationTime": "创建时间",
"AreYouSure": "确定吗?",
"AreYouSureToDelete": "确定要删除此项吗?",
"Enum:BookType.0": "未定义",
"Enum:BookType.1": "冒险",
"Enum:BookType.2": "传记",
"Enum:BookType.3": "反乌托邦",
"Enum:BookType.4": "奇幻",
"Enum:BookType.5": "恐怖",
"Enum:BookType.6": "科学",
"Enum:BookType.7": "科幻",
"Enum:BookType.8": "诗歌"
}
}
- 本地化键名是任意的,你可以设置任何名称。我们针对特定文本类型推荐一些约定:
- 为菜单项添加
Menu:前缀。 - 使用
Enum:<枚举类型>.<枚举值>或<枚举类型>.<枚举值>命名约定来本地化枚举成员。这样处理后,ABP 可以在某些适当场景下自动对枚举进行本地化。
- 为菜单项添加
如果本地化文件中未定义某个文本,它将回退到本地化键(遵循 ASP.NET Core 的标准行为)。
ABP 的本地化系统基于 ASP.NET Core 的标准本地化系统构建,并在许多方面进行了扩展。详情请参阅本地化文档。
创建书籍页面
是时候创建一些可见且可用的内容了!右键点击 Acme.BookStore.Blazor 项目下的 Pages 文件夹,添加一个新的 razor 组件,命名为 Books.razor:
将此组件的内容替换为以下内容:
@page "/books"
<h2>书籍</h2>
@code {
}
将书籍页面添加到主菜单
打开 Acme.BookStore.Blazor 项目中的 BookStoreMenuContributor 类,并在 ConfigureMainMenuAsync 方法的末尾添加以下代码:
context.Menu.AddItem(
new ApplicationMenuItem(
"BooksStore",
l["Menu:BookStore"],
icon: "fa fa-book"
).AddItem(
new ApplicationMenuItem(
"BooksStore.Books",
l["Menu:Books"],
url: "/books"
)
)
);
运行项目,使用用户名 admin 和密码 1q2w3E* 登录应用程序,你将看到新的菜单项已添加到主菜单:
当你点击 书店 父菜单下的 Books 菜单项时,将被重定向到新的空书籍页面。
书籍列表
我们将使用 Blazorise 库 作为 UI 组件套件。这是一个非常强大的库,支持主要的 HTML/CSS 框架,包括 Bootstrap。
ABP 提供了一个通用的基类 - AbpCrudPageBase<...>,用于创建 CRUD 风格的页面。此基类与用于构建 IBookAppService 的 ICrudAppService 兼容。因此,我们可以继承 AbpCrudPageBase 来自动化标准 CRUD 操作的后台代码。
打开 Books.razor 并将内容替换为以下内容:
@page "/books"
@using Volo.Abp.Application.Dtos
@using Acme.BookStore.Books
@using Acme.BookStore.Localization
@inherits AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>
<Card>
<CardHeader>
<h2>@L["Books"]</h2>
</CardHeader>
<CardBody>
<DataGrid TItem="BookDto"
Data="Entities"
ReadData="OnDataGridReadAsync"
TotalItems="TotalCount"
ShowPager="true"
PageSize="PageSize">
<DataGridColumns>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.Name)"
Caption="@L["Name"]"></DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.Type)"
Caption="@L["Type"]">
<DisplayTemplate>
@L[$"Enum:BookType.{context.Type}"]
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.PublishDate)"
Caption="@L["PublishDate"]">
<DisplayTemplate>
@context.PublishDate.ToShortDateString()
</DisplayTemplate>
</DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.Price)"
Caption="@L["Price"]">
</DataGridColumn>
<DataGridColumn TItem="BookDto"
Field="@nameof(BookDto.CreationTime)"
Caption="@L["CreationTime"]">
<DisplayTemplate>
@context.CreationTime.ToLongDateString()
</DisplayTemplate>
</DataGridColumn>
</DataGridColumns>
</DataGrid>
</CardBody>
</Card>
@code
{
public Books() // 构造函数
{
LocalizationResource = typeof(BookStoreResource);
}
}
如果你看到一些语法错误,但应用程序能够正确构建和运行,可以暂时忽略它们。Visual Studio 在处理 Blazor 时仍有一些 bug。
- 继承自
AbpCrudPageBase<IBookAppService, BookDto, Guid, PagedAndSortedResultRequestDto, CreateUpdateBookDto>,该基类为我们实现了所有 CRUD 细节。 Entities、TotalCount、PageSize、OnDataGridReadAsync在基类中已定义。LocalizationResource设置为BookStoreResource以本地化文本。
虽然上述代码相当容易理解,但为了更好地理解它们,你可以查阅 Blazorise 的 Card 和 DataGrid 文档。
关于 AbpCrudPageBase
我们将在书籍页面中继续利用 AbpCrudPageBase。你也可以直接注入 IBookAppService 并自行执行所有服务器端调用(这得益于 ABP 的动态 C# HTTP API 客户端代理系统)。为了演示如何在你的 Blazor 应用程序中调用服务器端 HTTP API,我们将在作者页面中手动操作。
运行最终应用程序
现在你可以运行应用程序了!本部分的最终 UI 如下所示:
这是一个功能完整、服务器端分页、排序和本地化的书籍表格。
抠丁客






