Blazor WASM .NET5未知深度递归组件按需渲染及避免无限递归方案问询
问题根因
你遇到的无限递归问题核心是没有给自引用的ChildResourceList加渲染判断条件:即使ChildVisible设为false,子组件依然会被实例化,只要传入了非空的ChildSelectedItem,子组件的OnParametersSetAsync就会执行,同时子组件自身也会默认渲染下一级的ChildResourceList,层层递归直接导致应用冻结。
修复方案
完全不需要创建多级子组件,仅修改几处代码即可实现按需渲染:
- 给自引用组件外层加渲染判断,不需要展示时直接不实例化子组件,从根源切断递归链路
- 补全子组件的关闭回调绑定,确保子组件关闭时能清空父级的选中状态
- 可额外加兜底判断,资源列表为空时不渲染子组件入口,避免无意义操作
修改后完整代码如下:
@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> <!-- 核心修改:仅需展示子层级时才渲染子组件 --> @if (ChildVisible && ChildSelectedItem != null) { <ChildResourceList SelectedItem="ChildSelectedItem" Visible="ChildVisible" OnClose="@OnChildClose"> </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 (Visible && SelectedItem != null && !ResourceList.Any()) { 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; } }
可选优化
- 可以给
Resource类加HasChildren标识字段,避免用户点击无下级的资源时发起无用API请求 - 接口请求过程中可添加加载状态提示,优化用户体验
- 层级过深时可增加全局折叠/展开控制,避免页面渲染过多元素导致卡顿
内容的提问来源于stack exchange,提问作者Kevon
相关产品推荐
相关产品推荐

