如何重构 Blazor OnParameterSet 中的代码

问题描述 投票:0回答:1

我有一组页面,它们都遵循类似的

/{report}/{id}
模式,但其中 {report} 被每个页面的具体名称替换。我们还有一个单例
reportManager
,它曾经在页面的 OnParameterSet

中更新
protected override async Task OnParametersSetAsync()
{
   if (reportManager.SelectedId != id) {
       reportManager.SelectedId = id;
   }

   var item = reportManager.SelectedItem;
}

现在此逻辑已移至每个页面使用的组件中。但是,由于页面将调用

reportManager.SelectedItem
,因此需要在页面的 OnParametersSetAsync 之前调用组件的 OnParametersSetAsync。

有什么方法可以重新排序这些东西,或者有更好的方法将该逻辑提取到某个常见的地方。

我考虑过继承,但在 blazor 组件中,如果您希望继承的组件包含派生组件,那么它有点丑陋且有点繁琐。

我还考虑过创建一些与

/{report}/{id}
匹配的页面,然后根据 {report} 参数提供正确的组件,但每次添加页面时,您都必须更新此“路由”页面。

否则我可能需要重新设计

reportManager
,因为它有点笨重

c# blazor blazor-server-side
1个回答
0
投票

正如@topsail所说,Blazor的组件生命周期事件遵循固定的顺序,我们无法直接对它们重新排序,但您可以使用生命周期事件来实现您的要求。这是您可以尝试的代码:

ReportState.cs:

namespace ReportManagementApp.Data
{
    public class ReportState
    {
        public string SelectedId { get; private set; }
        public string SelectedItem { get; private set; }

        public event Action OnChange;

        public void SetSelectedId(string id)
        {
            if (SelectedId != id)
            {
                SelectedId = id;
                // Fetch and set the selected item based on the ID
                SelectedItem = FetchSelectedItem(id);
                NotifyStateChanged();
            }
        }

        private string FetchSelectedItem(string id)
        {
            // Simulate fetching an item based on the ID
            return $"Item for ID: {id}";
        }

        private void NotifyStateChanged() => OnChange?.Invoke();

    }
}

ReportStateProvider.razor:

@using ReportManagementApp.Data
<h3>ReportStateProvider</h3>

@code {
    [Inject] private ReportState ReportState { get; set; } = default!;
    [Parameter] public string ReportId { get; set; } = default!;

    protected override async Task OnParametersSetAsync()
    {
        // Initialize the report state with the provided ReportId
        ReportState.SetSelectedId(ReportId);
    }
  }

ReportPage.razor:

@page "/report/{id}"
@using ReportManagementApp.Data
@inject ReportState ReportState

<h3>Report Page</h3>

<div>
    <p>Selected ID: @ReportState.SelectedId</p>
    <p>Selected Item: @ReportState.SelectedItem</p>
</div>

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

    protected override async Task OnParametersSetAsync()
    {
        // This ensures that ReportState has been set before you use it
        if (ReportState.SelectedId != Id)
        {
            ReportState.SetSelectedId(Id);
        }
    }
   }

NavMenu.razor:

 <div class="nav-item px-3">
     <NavLink href="/report/1" class="nav-link" Match="NavLinkMatch.Prefix">
         Report 1
     </NavLink>

 </div>

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.