【问题标题】:Blazor Layout with CascadingParameter initialized after component组件后初始化 CascadingParameter 的 Blazor 布局
【发布时间】:2021-12-03 16:04:15
【问题描述】:

有没有办法强制 Blazor 布局在其组件之前初始化?我发现它并不总是一致的,具体取决于访问页面的方式/时间。当我在组件所依赖的 Layout 中定义 CascadingParameter 时,它会导致问题。

组件设置:

@page "/parent1/parent2/parent3/things/1/details"
@layout MyLayout

// show thing here

@code
{
    [CascadingParameter] public object Thing { get; set; } // can be null

    protected override void OnInitialized() 
    {
        // this may occur before or after the layout is initialized

        // do something with Thing
    }
}

布局设置:

@inherits LayoutBase

@if (thing is not null) {
    <CascadingValue Value="@thing" IsFixed="true">
        @Body
    </CascadingValue>
}

@code {
    object thing;

    protected override void OnInitialized() 
    {
       // this may occur before or after the component is initialized
       thing = GetThingFromDatabase();

       // validate thing here
    }
}

我认为布局将是保护/验证/授权路由参数然后为任何子页面存储对象的最佳位置,但如果时间是随机的,则不起作用。例如,我追求的页面结构如下。

/things/1  (layout/abstract page)
   /things/1/details  (page using layout)
   /things/1/otherStuff  (page using layout)
   /things/1/moreStuff  (page using layout)

我只想加载一次,并在子页面之间导航时保​​留它。

【问题讨论】:

  • App.razor 将您的路由器设置为使用 MainLayout。更具体地说是RouteView

标签: blazor blazor-server-side


【解决方案1】:

有没有办法强制 Blazor 布局在其组件之前初始化?

您,程序员,无法控制组件实例化。这一切都由渲染器处理。

我只想加载一次并在子页面之间导航时保​​留它?

使用 Scoped Service 获取并持有事物 - ThingService - 并将其注入到任何需要它的组件中。

下面是一些示例代码:

首先是服务。注册为范围服务。

namespace StackOverflow.Server
{
    public class Thing
    {
        public string? ThisThing { get; set; }
        public bool Loading => this.ThisThing is null;

        public async Task GetThing()
        {
            // Emulated a real async database operation
            await Task.Delay(500);
            this.ThisThing = "Successful Database get";
        }
    }
}

演示级联的组件。

<h3>ShowThing Component</h3>
<div class="m-3">
Thing: @thing!.ThisThing
</div>

@code {
    [CascadingParameter] private Thing? thing { get; set; }
}

一个测试页面:

@page "/"
<CascadingValue Value=Thing>
    <ShowThing />
</CascadingValue>

<div class="m-3">
Thing: @this.Thing.ThisThing
</div>

@code {
    [Inject] Thing? Thing { get; set; }

    protected async  override Task OnInitializedAsync()
    {
        await Thing!.GetThing();
    }
}

请注意,如果 thing 不是 null,则无需测试。我已经删除了IsFixed,你不需要它。级联处理空值。当ThingOnInitializedAsync 中获得实际值时,OnInitializedAsync 后的渲染事件会检测到Thing 中的更改,并通过在这些组件上调用SetParametersAsync 将更改传递给为级联注册的任何组件,从而触发组件渲染。

【讨论】:

  • 在这个设置中,我注意到嵌套组件由于布局中的 if 语句而初始化了两次,但前提是组件在布局之前初始化。如果组件首先加载,则级联参数将为空。布局加载后它不会。在组件初始化时,我决定立即检查级联参数是否为空,如果是则中断,然后等待组件第二次初始化(在布局初始化后不久)。该页面看起来不错,但我猜这不是 Blazor 的良好工作流程。
  • 正确。请参阅我的更新答案。我在测试页面中运行它,但您可以在布局中实现它。请注意 cmets 在设置级联参数时不需要检查thing。您应该始终使用服务来保存、获取和管理您的数据。将所有这些都排除在 UI 之外。了解组件生命周期和渲染是非常非常重要的。它可以避免多次射击自己的脚!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 2020-05-07
  • 2021-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
相关资源
最近更新 更多