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

如何控制Razor组件结构?Blazor设计系统组件实现需求

解决方案

要实现你需要的嵌套组件结构、父组件控制渲染位置以及外部可访问子组件属性的需求,核心是通过**级联参数(CascadingParameter)**让子组件主动注册到父组件,父组件收集子组件实例后按自定义结构渲染。以下是具体实现:

1. 修改父组件 Card.razor

父组件需要维护子组件的实例引用,并提供注册方法,同时自定义渲染结构:

<div class="container-card">
    <!-- 按自定义顺序渲染收集到的子组件 -->
    @if (_cardDescription != null)
    {
        <div class="something-desc">
            @_cardDescription
        </div>
    }
    @if (_cardBody != null)
    {
        <div class="something-body">
            @_cardBody
        </div>
    }
    <!-- 处理其他未被收集的子内容 -->
    @if (_remainingContent != null)
    {
        <div class="some-other-child">
            @_remainingContent
        </div>
    }
</div>

@code {
    private CardDescription? _cardDescription;
    private CardBody? _cardBody;
    private CardTitle? _cardTitle;
    private RenderFragment? _remainingContent;

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    // 注册子组件的方法
    public void RegisterCardDescription(CardDescription desc) => _cardDescription = desc;
    public void RegisterCardBody(CardBody body) => _cardBody = body;
    public void RegisterCardTitle(CardTitle title) => _cardTitle = title;

    protected override void OnParametersSet()
    {
        // 重置子组件引用,避免重复注册
        _cardDescription = null;
        _cardBody = null;
        _cardTitle = null;
        base.OnParametersSet();
    }
}

2. 修改子组件 CardDescription.razor

通过级联参数获取父组件Card实例,在初始化时注册自己:

<div class="container-card-desc @GetAlignClass()">
    @ChildContent
</div>

@code {
    [CascadingParameter]
    private Card? ParentCard { get; set; }

    [Parameter]
    public string? AlignParam { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    protected override void OnInitialized()
    {
        ParentCard?.RegisterCardDescription(this);
        base.OnInitialized();
    }

    // 示例:根据AlignParam生成样式类
    private string GetAlignClass() => AlignParam switch
    {
        "Left" => "text-left",
        "Right" => "text-right",
        _ => "text-center"
    };
}

3. 修改子组件 CardTitle.razor

同样通过级联参数注册到父组件:

<div class="container-card-title @GetSizeClass()">
    @ChildContent
</div>

@code {
    [CascadingParameter]
    private Card? ParentCard { get; set; }

    [Parameter]
    public string? SizeParam { get; set; }

    [Parameter]
    public string? OtherParam { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    protected override void OnInitialized()
    {
        ParentCard?.RegisterCardTitle(this);
        base.OnInitialized();
    }

    private string GetSizeClass() => SizeParam switch
    {
        "big" => "text-2xl font-bold",
        "medium" => "text-xl font-semibold",
        _ => "text-lg font-normal"
    };
}

4. 修改子组件 CardBody.razor

<div class="container-card-body @BodyParam">
    @ChildContent
</div>

@code {
    [CascadingParameter]
    private Card? ParentCard { get; set; }

    [Parameter]
    public string? BodyParam { get; set; }

    [Parameter]
    public string? OtherParam { get; set; }

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    protected override void OnInitialized()
    {
        ParentCard?.RegisterCardBody(this);
        base.OnInitialized();
    }
}

5. 使用方式(和你期望的完全一致)

在Index.razor中直接嵌套使用:

<Card>
    <CardDescription AlignParam="None">
        <CardTitle SizeParam="big" OtherParam="happy">
            Amazing title
        </CardTitle>
    </CardDescription>
    <CardBody BodyParam="rounded-card blue-card">
        other longer content
    </CardBody>
</Card>

关键说明

  • 子组件注册逻辑:子组件通过CascadingParameter自动获取父组件Card的实例,在初始化时调用注册方法把自己传递给父组件,父组件就能收集到所有嵌套的子组件。
  • 渲染控制:父组件完全控制子组件的渲染位置和顺序,比如你可以把CardTitle从CardDescription中提取出来单独渲染,只需要修改父组件的渲染逻辑即可。
  • 外部访问属性:子组件的AlignParam、SizeParam等参数依然可以在外部直接设置,完全满足你的第三个需求。
  • 重置机制:父组件的OnParametersSet方法中重置子组件引用,避免组件刷新时出现重复注册的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:37:27