【问题标题】:Blazor optional route parametersBlazor 可选路由参数
【发布时间】:2019-04-17 17:19:03
【问题描述】:

使用dotnet new blazor 创建新的 blazor 项目。修改Index.cshtml

@page "/"
@page "/{Id}"

<h1>Id = @Id</h1>

<p><a href="/">Without Id</a></p>
<p><a href="/15">With Id = 15</a></p>

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

运行应用程序。

当我点击With Id = 15 链接时,一切都按预期工作- url 已更改,参数{Id} 被分配给值Id,一切正常。

但是当我点击 Without Id 链接之后,url 已经改变,但我的 ID 保持不变 - 等于 15。

为什么我的价值没有改变?我在这里想念什么?我该如何解决这个问题?

【问题讨论】:

  • 在 Param 上尝试了默认的空字符串值吗?
  • @HenkHolterman 控制台中没有任何内容。该页面未加载 - 当我单击链接时没有对服务器的请求。这是 blazor。
  • @MisterMagoo 默认空字符串没有帮助。
  • 这个类似问题的答案可能会对您有所帮助:stackoverflow.com/questions/59568084/…

标签: blazor


【解决方案1】:

支持可选路由参数as of ASP.NET Core 5.0

例如:

@page "/RouteParameter/{text?}"

<h1>Blazor is @Text!</h1>

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

    protected override void OnInitialized()
    {
        Text = Text ?? "fantastic";
    }
}

【讨论】:

  • 这应该是公认的答案。
【解决方案2】:

此行为是设计使然。 请注意,更改的 url 并不意味着当前页面已更改。以下 JavaScript 函数执行更改 url 的内部导航:

function performInternalNavigation(absoluteInternalHref: string) {
  history.pushState(null, /* ignored title */ '', absoluteInternalHref);
  handleInternalNavigation();
} 

来源:https://github.com/aspnet/AspNetCore/blob/93127b39e824181d4f9b1a62b6fc8d10c481e2c8/src/Components/src/Microsoft.AspNetCore.Components.Browser.JS/src/Services/UriHelper.ts

调用 history.pushState 会导致 URL 栏显示“.../15”,但不会导致浏览器加载新的 url,或者更确切地说会导致 Blazor 重新创建 Index 组件。如果仅 URL 参数发生更改,Blazor 不会重新创建组件。由于您已经在索引页面上,因此单击“无 ID”链接不会导致索引组件重新呈现。而是重用当前的 Component 实例,但是可惜这个实例组件的参数属性设置为值 15,并且不会被“遍历 ParameterCollection,将每个参数分配给同名属性的 AssignToProperties 方法覆盖”估计的正好。”但是 ParameterCollection 不包含 Id 参数;回想一下,这发生在您点击“Without Id”之后。同样,最终结果是具有包含值 15 的参数属性 Id。 来源:https://github.com/aspnet/Blazor/blob/29f925852b0a5e81e82780e0c1c32b486f7c3be6/src/Microsoft.AspNetCore.Blazor/Components/ParameterCollectionExtensions.cs

解决此问题的解决方法:

  1. 像这样重写 SetParameters 方法:
public override void SetParameters(ParameterCollection parameters)
{
   if (string.IsNullOrEmpty(parameters.GetValueOrDefault<string>("Id")))
   {
      Id = null;
   }
   base.SetParameters(parameters);
}
  1. 通过继承 Router 实现自定义路由逻辑

希望这会有所帮助...

【讨论】:

  • 谢谢。这确实说明了问题。作为一种解决方法,我已经注册了OnLocationChanged 并在那里应用了我的自定义逻辑,但这似乎是一种 hack,而不是正确的逻辑。类似于:learn-blazor.com/pages/router/#accessing-query-parameters 你不认为,在通过 ParameterCollection 迭代期间,应该清除未分配的参数吗?恕我直言,这正是用户所期待的......
  • 每个解决方案都可能看起来像是一个 hack,包括您当前的解决方案。正如我上面所说,这种行为是设计使然。为了解决这个看似有缺陷的设计,人们进行了几次尝试,但都没有成功。根据史蒂夫·桑德森(Steve Sanderson)的说法,改变这种设计的条件应该是一种无需任何额外性能成本且无需进一步反思即可实现的设计......你能做到吗
【解决方案3】:

更简单的解决方案是将 Id 设置为 null。 “如果”不是必需的。

public override void SetParameters(ParameterCollection parameters)
{
    Id = null;
    return base.SetParameters(ParametersCollection parameters)
}

或者更当前的异步等效项

【讨论】:

    【解决方案4】:

    试试这个

    @page "/"
    @page "/{Id:string}"
    
    <h1>Id = @Id</h1>
    
    <p><NavLink href="/">Without Id</NavLink></p>
    <p><NavLink href="/15">With Id = 15</NavLink></p>
    
    @code{
      [Parameter]
      public string Id {get;set;}
    }
    

    希望您的问题得到解决

    【讨论】:

      【解决方案5】:

      简单的解决方法是删除第一条路线。它让路由器忽略您的(丢失的)参数。然后使用 ? 使 Id 成为可选:

      @page "/" -- remove this line
      @page "/{Id?}"
      

      现在将始终将某些内容分配给Id,如果不存在则为 null。

      【讨论】:

      • 这只是我可以创建的最简单的示例。我的真实案例是:我在页面clients/1234 上显示了客户的详细信息,并且我离开了带有 链接的导航菜单项。因此,当我单击左侧菜单链接时,页面不会刷新。
      • 我收集到了,但推理仍然存在:您仍然会转到客户页面,并且仍在查看 1234 .... 您想到了哪些刷新,为什么不做一个/clients 和 /clients/details/id ?
      • 因为 /clients 基本上只是搜索框,当 /clients/id 是相同的搜索框 + 客户的详细信息时。我不想创建两个单独的页面,只需添加 if (!string.IsNullOrEmpty(id)) { // show details } 元素。
      【解决方案6】:

      带有路由约束的可选路由参数示例:

      @page "/user/{Id:int}/{Option:bool?}"
      
      <p>
          Id: @Id
      </p>
      
      <p>
          Option: @Option
      </p>
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public bool Option { get; set; }
      }
      

      https://docs.microsoft.com/en-us/aspnet/core/blazor/fundamentals/routing?view=aspnetcore-6.0#route-constraints

      其他一些有效和无效的示例:

      /product/5 - Works
      /product/5/2 - Works
      
      @page "/product/{Id:int}/{TabId:int?}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public int? TabId { get; set; }
      }
      
      /product/5 - Works
      /product/5/2 - Works but needs to be manually converted
      
      @page "/product/{Id:int}/{TabId?}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public string TabId { get; set; }
      }
      
      /product/5 - Works
      /product/5/2 - System.InvalidCastException: Specified cast is not valid.
      
      @page "/product/{Id:int}/{TabId?}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public int? TabId { get; set; }
      }
      
      /product/5 - Sorry, there's nothing at this address.
      /product/5/2 - System.InvalidOperationException: Object of type 'Project.Client.Pages.ProductDetails' does not have a property matching the name 'TabId?'.
      
      @page "/product/{Id:int}/{TabId?:int}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public int? TabId { get; set; }
      }
      
      /product/5 - System.InvalidOperationException: Object of type 'Project.Client.Pages.ProductDetails' does not have a property matching the name 'TabId?'.
      /product/5/2 - System.InvalidOperationException: Object of type 'Project.Client.Pages.ProductDetails' does not have a property matching the name 'TabId?'.
      
      @page "/product/{Id:int}/{TabId?:int?}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public int? TabId { get; set; }
      }
      
      /product/5 - Sorry, there's nothing at this address.
      /product/5/2 - System.InvalidOperationException: Object of type 'Project.Client.Pages.ProductDetails' does not have a property matching the name 'TabId?'.
      
      @page "/product/{Id:int}/{TabId?:int}"
      
      @code {
          [Parameter]
          public int Id { get; set; }
      
          [Parameter]
          public int TabId { get; set; }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-04-18
        • 2020-02-15
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 2012-03-24
        • 2015-02-05
        • 1970-01-01
        相关资源
        最近更新 更多