Blazor UI:主题系统
简介
ABP提供了一个完整的UI主题系统,其目标如下:
- 可重用的 应用程序模块 是独立于主题开发的,因此它们可以与任何UI主题配合使用。
- UI主题由最终的应用程序决定。
- 主题通过NuGet包分发,因此易于升级。
- 最终应用程序可以自定义所选主题。
为了实现这些目标,ABP:
- 确定了一套所有主题都使用和适配的基础库。因此,模块和应用程序开发者可以依赖并使用这些库,而无需依赖于特定主题。
- 提供了一个由所有主题实现的布局部件系统(如导航菜单和工具栏)。因此,模块和应用程序可以贡献到布局中,从而构成一个一致的应用程序UI。
当前提供的主题
目前,官方提供了三个主题:
概述
基础库
所有主题都必须依赖于Volo.Abp.AspNetCore.Components.WebAssembly.Theming NuGet包,因此它们间接依赖于以下库:
- Twitter Bootstrap 作为基础的HTML/CSS框架。
- Blazorise 作为组件库,支持Bootstrap并添加了额外的组件,如数据网格和树。
- FontAwesome 作为基础的CSS字体库。
- Flag Icon 作为显示国家旗帜的库。
这些库被选为基础库,可供应用程序和模块使用。
由于Blazorise库已经以原生方式为Bootstrap组件提供了必要的功能,因此不使用Bootstrap的JavaScript部分。
布局
所有主题都必须为应用程序定义一个布局。下图显示了基础主题应用程序布局中的用户管理页面:
同一页面在Lepton主题应用程序布局中的显示如下:
如您所见,页面相同,但上述主题中的外观完全不同。
应用程序布局通常包括以下部分:
实现主题
主题本质上是一个Razor类库。
最简单的方法
创建新主题的最简单方法是添加基础主题源代码模块及其源代码,然后进行自定义。
abp add-package Volo.Abp.AspNetCore.Components.WebAssembly.BasicTheme --with-source-code --add-to-solution-file
全局样式/脚本
主题通常需要向页面添加全局样式。ABP提供了一个系统来管理全局样式和脚本。主题可以实现IBundleContributor接口,以向页面添加全局样式或脚本文件。
示例:向页面添加样式
using Volo.Abp.Bundling;
namespace MyTheme
{
public class MyThemeBundleContributor : BundleContributor
{
public override void ConfigureBundle(BundleConfigurationContext context)
{
context.Files.AddIfNotContains("_content/MyTheme/styles.css");
}
}
}
[DependsOn(
typeof(AbpAspNetCoreComponentsWebAssemblyThemingBundlingModule)
)]
public class MyBlazorWebAssemblyBundlingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpBundlingOptions>(options =>
{
// 添加样式捆绑包
options.StyleBundles.Get(BlazorWebAssemblyStandardBundles.Styles.Global)
.AddContributors(typeof(MyThemeBundleContributor));
});
}
}
在此示例中,styles.css文件应添加到主题项目的wwwroot文件夹中。
有关更多信息,请参阅全局样式和脚本文档。
布局部件
典型的布局由多个部件组成。主题应在每个布局中包含必要的部件。
示例:基础主题的应用程序布局包含以下部件
应用程序代码和模块只能在页面内容部分显示内容。如果它们需要更改其他部分(例如添加菜单项、添加工具栏项、更改品牌标识区域中的应用程序名称等),则应使用ABP的API。
以下部分解释了ABP预定义的基本部件,这些部件可以由主题实现。
将布局拆分为组件/部分是一个良好的实践,这样最终应用程序可以根据需要部分覆盖它们以实现自定义。
品牌标识
应使用IBrandingProvider服务来获取应用程序的名称和徽标URL,以便在品牌标识部分渲染。
应用程序启动模板 实现了此接口,以便应用程序开发者设置这些值。
主菜单
IMenuManager服务用于获取主菜单项并在布局上渲染。
示例:获取主菜单以在Razor组件中渲染
// Razor组件的代码后置文件
public partial class NavMenu
{
private readonly IMenuManager _menuManager;
public NavMenu(IMenuManager menuManager)
{
_menuManager = menuManager;
}
protected override async Task OnInitializedAsync()
{
var menu = await _menuManager.GetAsync(StandardMenus.Main);
//...
}
}
有关导航系统的更多信息,请参阅导航/菜单文档。
主工具栏
IToolbarManager服务用于获取主工具栏项并在布局上渲染。此工具栏的每个项都是一个Razor组件,因此可以包含任何类型的UI元素。注入IToolbarManager并使用GetAsync获取工具栏项:
var toolbar = await _toolbarManager.GetAsync(StandardToolbars.Main);
有关工具栏系统的更多信息,请参阅工具栏文档。
主题有责任向主工具栏添加两个预定义项:语言选择和用户菜单。为此,创建一个实现IToolbarContributor接口的类,并将其添加到AbpToolbarOptions中,如下所示:
Configure<AbpToolbarOptions>(options =>
{
options.Contributors.Add(new BasicThemeMainTopToolbarContributor());
});
语言选择
语言选择工具栏项通常是一个下拉菜单,用于在语言之间切换。使用ILanguageProvider获取可用语言列表,并使用CultureInfo.CurrentUICulture了解当前语言。
使用本地存储通过Abp.SelectedLanguage键获取和设置当前语言。
示例:获取当前选择的语言
var selectedLanguageName = await JsRuntime.InvokeAsync<string>(
"localStorage.getItem",
"Abp.SelectedLanguage"
);
示例:设置选择的语言
await JsRuntime.InvokeVoidAsync(
"localStorage.setItem",
"Abp.SelectedLanguage",
"en-US"
);
更改语言后,主题应重新加载页面:
await JsRuntime.InvokeVoidAsync("location.reload");
用户菜单
用户菜单包含与用户帐户相关的链接。像使用主菜单一样使用IMenuManager,但这次使用StandardMenus.User参数,如下所示:
var menu = await _menuManager.GetAsync(StandardMenus.User);
可以使用 ICurrentUser 和 ICurrentTenant 服务来获取当前用户和租户名称。
页面提示
IAlertManager服务用于获取当前页面提示并在布局上渲染。有关更多信息,请参阅页面提示文档。
抠丁客





