Blazor 》 Component。

ASP.NET Core Blazor layouts

Blazor的layout是一个Razor组件,可以将记标分享给其他组件,只要这些组件引用这个layout。

layout可以使用数据绑定,依赖注入,以及其他组件的特性。

Layout components

layout组件和普通组件类似,也是以.razor结尾,不过通常放在Shared目录。

layout组件时从LayoutComponentBase派生的,拥有一个Body辖属(类型为RenderFragment),可以使用@Body来插入内容。

例子: DoctorWhoLayout

讲解了项目模板中的MainLayout组件。并提到MainLayout使用CSS Isolation技术,即有专属的Shared/MainLayout.razor.css,对应代码在https://github.com/dotnet/aspnetcore/blob/main/src/ProjectTemplates/Web.ProjectTemplates/content/ComponentsWebAssembly-CSharp/Client/Shared/MainLayout.razor.css

Apply a layout

对于有@page指示的组件,只须加上@layout指示即可指定其layout。@layout指示会被转化为LayoutAttribute属性,应用在组件类上。

无路由的组件不适用layout

若想将同一layout应用于对某个目录下的组件,需要在该目录下创建一个_Imports.razor文件。此文件中的指示会被包含在目录以及子目录中的所有组件,如下所示:

@layout DoctorWhoLayout
...

不要在根目录的_Imports.razor添加@layout指示,会导致layout的无限循环。

若要将某layout应用于整个app,争取的做法时在App.razor的Router组件中声明,如下所示:

<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <p>Sorry, there's nothing at this address.</p>
    </NotFound>
</Router>

Apply a layout to arbitrary content (LayoutView component)

若要将layout应用于任意的Razor模板内容,可以使用LayoutView组件:

        <LayoutView Layout="@typeof(ErrorLayout)">
            <h1>Page not found</h1>
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>

Nested layouts

layout可以嵌套layout。方法是编译一个layout添加一个到其他layout的指示:

@inherits LayoutComponentBase
@layout ProductionsLayout

@Body

Share a Razor Pages layout with integrated components

略。

Control content in ASP.NET Core Blazor apps

Control content in a Razor component

采用以下方式指定页面标题:

<PageTitle>@title</PageTitle>

HeadContent组件的内容的插入位置由HeadOutlet指定。在WASM中HeadOutlet被添加到Program.Main中的RootComponents:

builder.RootComponents.Add<HeadOutlet>("head::after");

"head::after"意味这HeadContent的内容附加到既有内容,而不是替换之。

Blazor Server采用的方式略有不同

Not found page title

App组件中的NotFound组件会将其页面设为Not found:

<PageTitle>Not found</PageTitle>

看了一眼手头的工程,好像不是这样的。

ASP.NET Core Blazor cascading values and parameters

CascadingValue component

CascadingValue组件可以用于在某个前序节点上为所有后续递进节点提供一个共有值。这个层递值会沿树形结构下放。

以下例子中的theme字段作为层递值下放。

        <CascadingValue Value="theme">
            <div class="content px-4">
                @Body
            </div>
        </CascadingValue>
@code {
    private ThemeInfo theme = new() { ButtonClass = "btn-success" };
}

[CascadingParameter] attribute

接收层递值需要用到一个层递参数:

@code {
    [CascadingParameter]
    protected ThemeInfo ThemeInfo { get; set; }
}

层递值和层递参数是通过类型联系在一起的。

Cascade multiple values

若要层递多个值,须为这些层递值起不同的名字,且必须嵌套应用CascadingValue标记:

<CascadingValue Value="@parentCascadeParameter1" Name="CascadeParam1">
    <CascadingValue Value="@ParentCascadeParameter2" Name="CascadeParam2">
        ...
    </CascadingValue>
</CascadingValue>

@code {
    private CascadingType parentCascadeParameter1;

    [Parameter]
    public CascadingType ParentCascadeParameter2 { get; set; }

    ...
}

层递参数的话也要用名字区分:

...

@code {
    [CascadingParameter(Name = "CascadeParam1")]
    protected CascadingType ChildCascadeParameter1 { get; set; }

    [CascadingParameter(Name = "CascadeParam2")]
    protected CascadingType ChildCascadeParameter2 { get; set; }
}

Pass data across a component hierarchy

举例说明如何使用CascadingValue在不同的组件层次间传递数据。

(本篇完)