【问题标题】:I need to update a Blazor page to update whenever the query string changes每当查询字符串更改时,我都需要更新 Blazor 页面以进行更新
【发布时间】:2022-01-24 15:24:47
【问题描述】:

我有一个名为 NavBar.razor 的 Blazor 组件,它显示带有标签列表的 Radzen 导航菜单。当用户单击标签 (RadzenPanelMenuItem) 时,组件 OrderBrowser.razor 会加载到菜单旁边的页面中。查询字符串让 OrderBrowser.razor 知道选择了哪个标签。 (请参阅下面的 OnInitializedAsync 方法。)该组件将关联的订单加载到网格中。

这在用户第一次单击标签时工作正常,但是当他们单击不同的标签时,即使 uri 发生更改,OnInitializedAsync 方法也不会执行。所以我添加了一个事件处理程序来在 uri 更改时强制重新加载。这可行,但由于某种原因,它似乎重新加载了两次,导致第二次重新加载时出现不希望的闪烁。

有人知道更好的方法吗?谢谢。

来自 NavBar.razor 的代码:

@foreach (var item in TagsAndCounts)
{
    <Radzen.Blazor.RadzenPanelMenuItem 
        Text="@(item.Tag + " (" + item.Count + ")")"
        Path="@("orders/browse?tag=" + item.Tag)" />
}

来自 OrderBrowser.razor 的订单网格:

<OrderGrid Data="@orders" AllowPaging="false" />

来自 OrderBrowser.razor 的代码:

protected override async Task OnInitializedAsync()
{
    await base.OnInitializedAsync();

    NavManager.LocationChanged += NavManager_LocationChanged;

    var uri = NavManager.ToAbsoluteUri(NavManager.Uri);

    if (QueryHelpers.ParseQuery(uri.Query).TryGetValue("tag", out var tag))
    {
        orders = await orderService.GetOrdersForTagAsync(tag);
    }
}

private void NavManager_LocationChanged(object sender, LocationChangedEventArgs e)
{
    NavManager.NavigateTo(NavManager.Uri, forceLoad: true);
}

【问题讨论】:

  • 您是否需要对“标签”使用查询字符串?如果没有,那么您可以使用orders/browse/{tag} 的 URL 路径,然后将调用 OnInitializeAsync()。
  • 起初我以为这会起作用,但看起来只有在 URL 的订单/浏览部分发生更改时才会调用 OnInitializeAsync()。它忽略对 {tag} 的更改,就像忽略对查询字符串的更改一样。
  • 您是否正确创建了 Route 参数?这是一个资源:docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/…
  • 我相信是的。这是我的路线:@page "/orders/browse/{tag}"
  • 酷。你在OrderBrowser.razor 的顶部有那个@page,这很好。您是否定义了 tag C# 属性来接受标记值?如果是,那么您还需要更改您从 NavBar.razor 组件指向的 URL Path = "@("orders/browse/{item.Tag}"

标签: c# blazor radzen


【解决方案1】:

当您从:yourUrl/tag/tagname1 转到链接yourUrl/tag/tagname2 时,它不会触发OnInitializedAsync,因为没有创建新页面。这是有意的和正确的行为。但有点混乱。

您可以利用引入 .net6 的新功能 SupplyFromQueryParameter 属性,该属性将根据查询字符串更改其值。

 [Parameter, SupplyParameterFromQuery(Name = "tag")] public string Tag { get; set; } = "";

现在您可以在Tag 属性的seeter 中发挥作用。或者,如果您需要在 setter 中调用异步方法(这不是一个好习惯),您可以使用 OnParametersSet 方法。它在参数更改后立即调用。所以你还需要一种机制来检查标签参数是否已更改(因为每次 *some* 参数已更改时都会调用它)

bool tagUpdated = true;
string _tag ="";
[Parameter,SupplyParameterFromQuery] public string Tag { get => _tag; set { if (value != _tag) { _tag = value; tagUpdated = true; } } } 

protected override async Task OnParametersSetAsync()
{
if (tagUpdated)
    {
    tagUpdated = false;
    await YourAsyncCallAndOtherMagic();
    }
}

请注意,SupplyFromQueryParameter 仅适用于页面(带有 @page 指令的.razor 组件)

(我猜这仍然不是最漂亮的解决方案。欢迎提出建议...)

【讨论】:

  • 这不需要路由上下文吗?一个月前我尝试了类似的方法,但遗憾的是我不得不放弃,因为如果没有 hacky 变通办法,这将无法在 AppComponent 上运行。在 Angular 中,您可以从任何地方简单地订阅特定的查询参数,并采取相应的行动。
  • 我的公司还没有转到 .net6,但我会在我们这样做的时候记录下来。谢谢!
【解决方案2】:

我找到了解决方案。它仍然有点黑客,但它似乎工作。如果有人有更好的解决方案,请告诉我。我只是更改了事件处理程序以获取新 URL 并更新页面,而不是强制重新加载。

private async void NavManager_LocationChanged(object sender, LocationChangedEventArgs e)
{
    orders = await orderService.GetOrdersForTagAsync(tag);
    var index = NavManager.Uri.LastIndexOf("/");
    tag = NavManager.Uri.Substring(index + 1);
    if (tag != "open_orders")
    {
       StateHasChanged();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-02
    • 2012-08-29
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多