项目

Blazor UI:布局钩子

ABP主题系统将页面布局封装在主题NuGet包中。这意味着最终应用程序不包含布局代码,因此您无法直接修改布局代码来自定义它。

如果您使用ABP模板创建了Blazor应用程序,项目中会包含一个App.razor文件。您可以根据需求自定义该文件,甚至可以通过布局钩子进行扩展。

您可以将主题代码复制到解决方案中。这种情况下您可以完全自由地进行定制。但这样您将无法获得主题的自动更新(通过升级主题NuGet包)。

布局钩子系统允许您在布局的特定位置添加代码。所有主题的所有布局都应实现这些钩子。最终,您可以将Razor组件添加到钩子点。

示例:添加简单公告提示

假设您需要在布局中添加一个简单横幅(在所有页面显示)来发布新产品公告。首先,在项目中创建Razor组件

bookstore-banner-component

AnnouncementComponent.razor.cs

using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace Acme.BookStore.Blazor.Components;

public partial class AnnouncementComponent : ComponentBase
{
    private const string AnnouncementLocalStorageKey = "product-announcement-status";

    [Inject]
    public IJSRuntime JsRuntime { get; set; }

    public bool ShowBanner { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ShowBanner = await ShowAnnouncementBannerAsync();
    }

    private async Task<bool> ShowAnnouncementBannerAsync()
    {
        var announcementLocalStorageValue = await JsRuntime.InvokeAsync<string>("localStorage.getItem", AnnouncementLocalStorageKey);

        return announcementLocalStorageValue != null && 
               bool.TryParse(announcementLocalStorageValue, out var showAnnouncementBanner) && showAnnouncementBanner;
    }

    private async Task HideAnnouncementBannerAsync()
    {
        await JsRuntime.InvokeVoidAsync("localStorage.setItem", AnnouncementLocalStorageKey, true);
        ShowBanner = false;
        StateHasChanged();
    }
}

AnnouncementComponent.razor

@if(ShowBanner)
{
    <div class="alert alert-info">
        新品上市促销。[点击此处](/docs/zh-Hans/abp-docs/master/framework/ui/blazor/#)了解更多。
        <button @onclick="async () => { await HideAnnouncementBannerAsync(); }">隐藏</button>
    </div>
}

然后,在模块类的ConfigureServices方法中将此组件添加到任意钩子点:

Configure<AbpLayoutHookOptions>(options =>
{
    options.Add(
        LayoutHooks.Body.Last, //钩子名称
        typeof(AnnouncementComponent) //要添加的组件
    );
});

现在,AnnouncementComponent将在页面body末尾渲染。

指定布局

上述配置会将AnnouncementComponent添加到所有布局。如果只想添加到特定布局:

Configure<AbpLayoutHookOptions>(options =>
{
    options.Add(
        LayoutHooks.Body.Last,
        typeof(AnnouncementComponent),
        layout: StandardLayouts.Application //设置目标布局
    );
});

参阅下文布局章节了解布局系统详情。

布局钩子点

存在若干预定义的布局钩子点。标准钩子点包括:

  • LayoutHooks.Head.First:在HTML head标签开头添加组件
  • LayoutHooks.Head.Last:在HTML head标签末尾添加组件
  • LayoutHooks.Body.First:在HTML body标签开头添加组件
  • LayoutHooks.Body.Last:在HTML body标签末尾添加组件

您(或使用的模块)可以向同一钩子点添加多个项目。它们将按添加顺序全部呈现在布局中。

在App.razor中渲染LayoutHooks.Head

Blazor应用中的App.razor文件是应用入口点。如需在head标签间渲染布局钩子,需手动注册布局钩子:

@using Volo.Abp.AspNetCore.Components.Web.Theming.Components.LayoutHooks;
@using Volo.Abp.Ui.LayoutHooks;
@using Volo.Abp.AspNetCore.Components.Web.Theming.Layout;

<!DOCTYPE html>
<html>
<head>
    <LayoutHook Name="@LayoutHooks.Head.First" Layout="@StandardLayouts.Application" />

    // 您的head内容
    // ...

    <LayoutHook Name="@LayoutHooks.Head.Last" Layout="@StandardLayouts.Application" />
</head>
<body>
    // 您的body内容
    // ...
</body>
</html>

注册相关布局钩子后,即可按前述方法在指定位置定义渲染组件。

布局系统

布局系统允许主题定义标准命名布局,并允许任何页面根据用途选择合适布局。存在一个预定义布局:

  • "Application":应用程序的主布局(默认布局)。通常包含页头、菜单(侧边栏)、页脚、工具栏等。

该布局在StandardLayouts类中定义为常量。您当然可以创建自己的布局,但此布局是标准布局,所有主题都默认实现。

如果未指定布局,您的Razor组件将在所有布局中渲染。

布局位置

可在此处找到基础主题的MainLayout.razor文件。您可参考它构建自己的布局,或在需要时重写它。

另请参阅

在本文档中