未知深度的递归组件
Recursive Component of unknown depth
我正在使用 Blazor WASM 和 .Net 5。
我有一个深度未知的分层数据结构。当我的组件加载时,我会显示数据结构的第一级。当用户单击其中一个项目时,它应该在从 API 调用加载数据后加载下一个级别。然后,您可以继续点击,直到没有更多关卡。
我以为我可以用一个自引用组件来完成,但我得到的似乎是一个无限递归循环。我这么说是因为当我 运行 应用程序并单击初始列表中的某些内容时,应用程序会冻结。
“Blade”只是一些带有一些事件回调的 HTML 标记,以及一个“可见”属性。
“ForEach”是一个组件迭代器。它不应该对这些工作方式至关重要
该组件是“ChildResourceList”,如您所见,它有一个对自身的引用。
问题是...如何让嵌套的 ChildResourceList 按需呈现?有没有我可以采用的不同方法,而不必创建 GrandChildResouceList、GreatGrandchildResourceList 等内容
@inject IHttpClientFactory factory;
<Blade Visible="Visible" OnCloseButtonClick="OnClose" Title="@SelectedItem?.ResourceName">
<ForEach Context="r" Items="ResourceList">
<div @onclick="(() => SetChildItem(r.Item))">
@r.Item.ResourceName
</div>
</ForEach>
</Blade>
<ChildResourceList SelectedItem="ChildSelectedItem" Visible="ChildVisible"></ChildResourceList>
@code {
[Parameter] public EventCallback OnClose { get; set; }
[Parameter] public bool Visible { get; set; }
[Parameter] public Resource SelectedItem { get; set; }
Resource ChildSelectedItem { get; set; }
bool ChildVisible { get; set; }
List<Resource> ResourceList { get; set; } = new();
protected override async Task OnParametersSetAsync()
{
if (SelectedItem != null)
ResourceList = await GetResources();
}
async Task<List<Resource>> GetResources()
{
HttpClient client = factory.CreateClient(name: "api");
return await client.GetFromJsonAsync<List<Resource>>($"{Endpoints.Features.ResourceExplorer.GetChildResources}/{SelectedItem.ResourceUID.ToString()}");
}
void SetChildItem(Resource item)
{
ChildSelectedItem = item;
ChildVisible = true;
}
void OnChildClose()
{
ChildVisible = false;
ChildSelectedItem = null;
}
}
在标记部分看起来确实像无限递归。您的组件现在总是 有一个子部分。你需要一个 @if()
围绕递归:
@if (ChildSelectedItem != null)
{
<ChildResourceList SelectedItem="ChildSelectedItem" Visible="ChildVisible"></ChildResourceList>
}
您将 ChildVisible 传递给 Blade (<Blade Visible="Visible"
),但嵌套列表在该 Blade 之外。
我正在使用 Blazor WASM 和 .Net 5。
我有一个深度未知的分层数据结构。当我的组件加载时,我会显示数据结构的第一级。当用户单击其中一个项目时,它应该在从 API 调用加载数据后加载下一个级别。然后,您可以继续点击,直到没有更多关卡。
我以为我可以用一个自引用组件来完成,但我得到的似乎是一个无限递归循环。我这么说是因为当我 运行 应用程序并单击初始列表中的某些内容时,应用程序会冻结。
“Blade”只是一些带有一些事件回调的 HTML 标记,以及一个“可见”属性。 “ForEach”是一个组件迭代器。它不应该对这些工作方式至关重要
该组件是“ChildResourceList”,如您所见,它有一个对自身的引用。
问题是...如何让嵌套的 ChildResourceList 按需呈现?有没有我可以采用的不同方法,而不必创建 GrandChildResouceList、GreatGrandchildResourceList 等内容
@inject IHttpClientFactory factory;
<Blade Visible="Visible" OnCloseButtonClick="OnClose" Title="@SelectedItem?.ResourceName">
<ForEach Context="r" Items="ResourceList">
<div @onclick="(() => SetChildItem(r.Item))">
@r.Item.ResourceName
</div>
</ForEach>
</Blade>
<ChildResourceList SelectedItem="ChildSelectedItem" Visible="ChildVisible"></ChildResourceList>
@code {
[Parameter] public EventCallback OnClose { get; set; }
[Parameter] public bool Visible { get; set; }
[Parameter] public Resource SelectedItem { get; set; }
Resource ChildSelectedItem { get; set; }
bool ChildVisible { get; set; }
List<Resource> ResourceList { get; set; } = new();
protected override async Task OnParametersSetAsync()
{
if (SelectedItem != null)
ResourceList = await GetResources();
}
async Task<List<Resource>> GetResources()
{
HttpClient client = factory.CreateClient(name: "api");
return await client.GetFromJsonAsync<List<Resource>>($"{Endpoints.Features.ResourceExplorer.GetChildResources}/{SelectedItem.ResourceUID.ToString()}");
}
void SetChildItem(Resource item)
{
ChildSelectedItem = item;
ChildVisible = true;
}
void OnChildClose()
{
ChildVisible = false;
ChildSelectedItem = null;
}
}
在标记部分看起来确实像无限递归。您的组件现在总是 有一个子部分。你需要一个 @if()
围绕递归:
@if (ChildSelectedItem != null)
{
<ChildResourceList SelectedItem="ChildSelectedItem" Visible="ChildVisible"></ChildResourceList>
}
您将 ChildVisible 传递给 Blade (<Blade Visible="Visible"
),但嵌套列表在该 Blade 之外。