【问题标题】:basic component layout inheritance blazor基本组件布局继承 blazor
【发布时间】:2020-05-16 08:27:31
【问题描述】:

假设我的大多数组件都有一个标题。我想创建一个具有标头变量的基本组件,并使所有其他组件都从该组件继承并设置标头。所以我有

基础组件

@inherits LayoutComponentBase;

<h1>@header</h1>

@Body

@code {

    protected string header;
}

组件

@inherits BaseComponent;

"internal component text"

@code {
  protected override void OnInitialized()
    {
         base.header = "Setting header for the parent"
    }
}

这编译并显示没有错误,但基本标头没有显示。就像基础中的任何东西都没有被渲染一样。我做错了什么?

附言

我也尝试过@layout BaseComponent,甚至同时尝试了两个指令。

【问题讨论】:

  • 要解决这个问题,您需要学习 Blazor 组件模型和 Blazor 中的布局机制。没有捷径...

标签: blazor


【解决方案1】:

它永远不会以您显示的方式工作,因为从内部设置父组件上的属性不会触发渲染。 AFAIK 解决这个问题的正确方法是拥有一个独立的服务类,它拥有一些常见的状态(在你的情况下,是当前页面标题),并通过事件操作将其注入到需要更改它的每个组件中:

应该是这样的:

public class GlobalUtilities
{
    public string MainPageTitle { get; private set; } = "Home (default value)";

    public event Action OnMainTitleChanged;

    public void SetMainTitle(string text)
    {
        MainPageTitle = text;
        OnMainTitleChanged.Invoke();
    }
}

在 Startup.cs 的管道上注册它:

services.AddScoped<UtilsGlobales>();

它应该注册为作用域,因为它的生命周期与当前连接配对。

然后在你需要的所有后代组件上使用它:

组件

//No need to inherit, only inject...
// @inherits BaseComponent;

@inject GlobalUtilities gu

<p>Something here</p>

@code {
    protected void OnInitialized()
    {
        gu.SetMainTitle("Whatever you want");
    }
}

希望对你有帮助!

【讨论】:

  • 父组件的静态内容(我有一些测试词)也没有显示出来……就像父组件不存在一样。
【解决方案2】:

在撰写本文时,派生的 razor 组件自动实现其基类的所有方法,包括 BuildRenderTree(呈现您在 razor 文件中键入的 HTML 标记)。当您不键入任何内容时,该方法将不会尝试自行调用基本 BuildRenderTree 方法。所以你需要像这样手动完成:

@inherits BaseComponent;

@{
    base.BuildRenderTree(__builder);
}

@code {
  protected override void OnInitialized()
    {
         base.header = "Setting header for the parent"
    }
}

【讨论】:

  • 在 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它如何解决问题。请编辑您的答案以解释此代码如何回答问题以及它如何改进现有问题,以便它对 OP 以及其他有类似问题的用户有用。
  • @FluffyKitten 你说得对,现在是凌晨 2 点,我的大脑被炸了。我添加了一些细节!
【解决方案3】:

扩展@sw1337 答案,如果派生组件没有降价,您可以将其创建为常规 cs 文件而不是 razor 文件,并且无需调用基本 BuildRenderTree 方法即可按预期工作。有关详细信息,请参阅此github

简单示例

基础组件 (MyAbstractComponent.razor)

<h1>@header</h1>

@code {
    protected string header;
}

派生组件

public class MyDerivedComponent : MyAbstractComponent
{
    protected override void OnInitialized()
    {
         header = "set header from derived component";
    }
}

参数示例

基础组件 (MyAbstractComponent.razor)

<h1>@Header</h1>

@code {
  [Parameter] public string Header { get; set; }
}

派生组件

public class MyDerivedComponent : MyAbstractComponent
{
    protected override void OnParametersSet()
    {
        // coalesce
        Header ??= "Default Header from derived Component"
    }
}

用法 1 - 派生组件的默认标头

一些 Razor 文件

<MyDerivedComponent></MyDerivedComponent>

结果

<h1>Default Header from derived Component</h1>

用法 2 - 来自派生消费者的指定标头

一些 Razor 文件

<MyDerivedComponent Header="MyHeader"></MyDerivedComponent>

结果

<h1>MyHeader</h1>

RenderFragment 参数示例

Blazor Fiddle

MyBaseComponent.razor

<h3>@Header</h3>

@if (ChildContent is not null)
{
    @ChildContent
}

@code {
    [Parameter] public string Header { get; set; }
    [Parameter] public RenderFragment ChildContent { get; set; }
}

MyDerivedComponent.cs

public class MyDerivedComponent : MyBaseComponent
{
    protected override void OnParametersSet()
    {
        // coalesce
        Header ??= "Derived Component Header";
        ChildContent ??= CreateDefaultChildContent();
    }
        
    private static RenderFragment CreateDefaultChildContent()
    {
        return builder =>
        {
            builder.OpenElement(0, "h4");
            builder.AddContent(1, "Derived Component default child content value");
            builder.CloseElement();
        };
    }
}

使用 MyRazorPage.razor

示例一 消费者不传递任何参数。使用派生组件中HeaderChildContent 的默认值。

代码

<MyDerivedComponent/>

输出

<h3>Derived Component Header</h3>
<h4>Derived Component default child content value</h4>

示例二 消费者传递Header参数,默认使用派生组件的ChildContent

代码

<MyDerivedComponent Header="Consumer Header"/>

输出

<h3>Consumer Header</h3>
<h4>Derived Component default child content value</h4>

示例三 消费者同时传递HeaderChildContent 参数。

代码

<MyDerivedComponent Header="Consumer Header">
    <h4>Child Content - from consumer</h4> 
</MyDerivedComponent>

输出

<h3>Consumer Header</h3>
<h4>Child Content - from consumer</h4>

【讨论】:

    猜你喜欢
    • 2020-09-10
    • 2022-11-16
    • 2021-04-05
    • 2020-06-01
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多