You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor实现兼具模板组件与布局特性、支持必填参数的可复用页面方案

实现方案

核心原理

使用Blazor原生的[RenderMethod]特性+抽象基类组合,既满足编译期必填参数校验,又保证布局统一,同时完全符合预期的业务页面写法。

实现步骤

1. 定义抽象基类 GridPage.cs

using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

// 指示所有继承该类的razor组件,将标记内容编译到RenderPageContent方法,而非默认的BuildRenderTree
[RenderMethod(nameof(RenderPageContent))]
public abstract class GridPage : ComponentBase
{
    /// <summary>
    /// 页面标题,抽象属性强制子类实现,漏写直接触发编译报错,天然支持必填校验
    /// </summary>
    protected abstract string Title { get; }

    /// <summary>
    /// 子类页面内容渲染方法,由razor编译器自动生成实现
    /// </summary>
    protected abstract void RenderPageContent(RenderTreeBuilder builder);

    /// <summary>
    /// 密封顶层渲染逻辑,子类无法修改,保证所有继承页面的布局统一
    /// </summary>
    protected sealed override void BuildRenderTree(RenderTreeBuilder builder)
    {
        // 渲染统一头部
        builder.OpenElement(0, "header");
        builder.AddContent(1, Title);
        builder.CloseElement();

        // 渲染内容容器
        builder.OpenElement(2, "div");
        // 渲染子类自定义的Grid内容
        RenderPageContent(builder);
        builder.CloseElement();
    }
}

2. 业务页面实现

以学生列表页Students.razor为例:

@page "/students"
@inherits GridPage

<Grid RowType=Student>
    <Column For="StudentName" />
    <Column For="StudentAge" />
    <Column For="StudentHomeRoom" />
</Grid>

@code {
    protected override string Title => "Students";
}

班级列表页Classes.razor同理:

@page "/classes"
@inherits GridPage

<Grid RowType=Class>
    <Column For="ClassName" />
    <Column For="ClassTime" />
</Grid>

@code {
    protected override string Title => "Classes";
}

效果说明

  • 编译期强制校验:如果子类漏写Title属性的重写,直接编译报错,不需要手动记忆参数
  • 布局完全统一:所有页面自动渲染统一的header+内容容器结构,子类不需要手动包裹任何模板组件
  • 性能无额外开销:没有多余的级联参数、嵌套组件,完全原生渲染逻辑
  • 业务页面写法极简:仅需继承基类、实现Title、写Grid配置即可,不需要任何额外代码

内容的提问来源于stack exchange,提问作者thalacker

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:36:03