是否有任何方法可以强制Blazor布局在其组件之前进行初始化?我发现它并不总是一致的,这取决于访问页面的方式/时间。当我在组件所依赖的布局中定义了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
}
}
我认为Layouts是保护/验证/授权路由参数,然后为任何子页面存储对象的最佳位置,但如果时间是随机的,那就行不通了。例如,我正在寻找如下页面结构。
/things/1 (layout/abstract page)
/things/1/details (page using layout)
/things/1/otherStuff (page using layout)
/things/1/moreStuff (page using layout)
我只想加载一次东西,并在它们在子页面之间导航时将其保留。
有什么方法可以强制Blazor布局在其组件之前初始化吗?
作为程序员,您无法控制组件实例化。这一切都由渲染器处理。
我只想加载一次东西,并在它们在子页面之间导航时保留它?
使用一个获取和保存ThingService的Scoped Service,并将其注入任何需要它的组件中。
下面是一些示例代码:
首先是服务。注册为作用域服务。
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
,你不需要它。级联处理null。当Thing
在OnInitializedAsync
中获得实际值时,后OnInitializedAsync
渲染事件检测到Thing
中的更改,并通过在这些组件上调用SetParametersAsync
将更改传递给为级联注册的任何组件,从而触发组件渲染。