导航管理器 - 在 Blazor 组件中获取当前 URL

107

为了检查是否需要对元素应用某种样式,我需要知道当前页面的 URL。以下代码是一个示例。

    @using Microsoft.AspNetCore.Blazor.Services
    @inject IUriHelper UriHelper
    @implements IDisposable

    <h1>@url</h1>
    <nav>
        <div class="nav-wrapper">
            <a href="#" class="brand-logo">Blazor</a>
            <ul id="nav-mobile" class="right hide-on-med-and-down">
                <li>
                    <NavLink href="/" Match=NavLinkMatch.All>
                        Home
                    </NavLink>
                </li>
                <li>
                    <NavLink href="/counter">
                        Counter
                    </NavLink>
                </li>
                <li>
                    <NavLink href="/fetchdata">
                        Fetch data
                    </NavLink>
                </li>
            </ul>
        </div>
    </nav>

    @functions {

        private string url = string.Empty;

        protected override void OnInit()
        {
            url = UriHelper.GetAbsoluteUri();
            UriHelper.OnLocationChanged += OnLocationChanged;
        }

        private void OnLocationChanged(object sender, LocationChangedEventArgs e)
        {
            url = newUriAbsolute;
        }

        public void Dispose()
        {
            UriHelper.OnLocationChanged -= OnLocationChanged;
        }
    }

我采用了Blazor存储库中NavLink组件使用的相同方法,但它没有起作用。有任何想法吗?


GetAbsoluteUri() 对我来说是有效的,问题到底出在哪里? - Flores
6个回答

230
使用 NavigationManager 类的 Uri 属性。

工作原理

.razor 页面上使用之前,从注入中获取它:

@inject NavigationManager MyNavigationManager

如果您更喜欢“代码后台”体验,则可以在 .cs 文件中这样写:

using Microsoft.AspNetCore.Components;
// ...
[Inject]
public NavigationManager MyNavigationManager {get; set;} = default!;

示例

@page "/navigate"
@inject NavigationManager MyNavigationManager

<h1>Current URL</h1>

<p>@(MyNavigationManager.Uri)</p>

更多关于导航的内容(NavigateTo,BaseUri,ToAbsoluteUri,ToBaseRelativePath等)在此处查看:URI和导航状态助手

NavigationManager速查表

MyNavigationManager.Uri
#> https://localhost:5001/counter/3?q=hi

MyNavigationManager.BaseUri
#> https://localhost:5001/

MyNavigationManager.NavigateTo("http://new location")
#> Navigates to new location

MyNavigationManager.LocationChanged
#> An event that fires when the navigation location has changed.

MyNavigationManager.ToAbsoluteUri("pepe")
#> https://localhost:5001/pepe

MyNavigationManager.ToBaseRelativePath(MyNavigationManager.Uri)
#> counter/3?q=hi

Helper: AddQueryParm( "q2", "bye" ) // (*1)
#> https://localhost:5001/counter/3?q=hi&q2=bye

Helper: GetQueryParm( "q" )
#> hi

(*1) Net6 引入了 GetUriWithQueryParameter 方法。更多信息请参考:在 Blazor 中操作查询字符串

帮助代码:

@code {

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

    // Blazor: add parm to URL
    string AddQueryParm(string parmName, string parmValue)
    {
        var uriBuilder = new UriBuilder(MyNavigationManager.Uri);
        var q = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
        q[parmName] = parmValue;
        uriBuilder.Query = q.ToString();
        var newUrl = uriBuilder.ToString();
        return newUrl;
    }

    // Blazor: get query parm from the URL
    string GetQueryParm(string parmName)
    {
        var uriBuilder = new UriBuilder(MyNavigationManager.Uri);
        var q = System.Web.HttpUtility.ParseQueryString(uriBuilder.Query);
        return q[parmName] ?? "";
    }

}

2
从v0.8.0开始,当使用服务器端模式时,您应该使用:@inject Microsoft.AspNetCore.Components.Services.IUriHelper UriHelper而当使用客户端模式时:@inject Microsoft.AspNetCore.Blazor.Services.WebAssemblyUriHelper UriHelper - Henry Rodriguez
6
@Henry Rodriguez,不对,正确的方法是注入IUriHelper接口而不是其实现。 - enet
如果用户试图通过URL地址强制转到另一页,则无法正常工作。 - Bcktr
2
这张备忘单非常有用 +1 - puerile
Cheatsheet GetQueryParam 只适用于查询参数,那么如何获取路由参数呢? - undefined
完整的广告文档 路由参数 - undefined

9

首先,将NavigationManager注入到需要获取当前URL的组件中,如下所示:

@inject NavigationManager NavManager

现在使用以下代码获取当前 URL:

string Url = NavManager.Uri.ToString();

4

在我的情况下,我只需要页面的Uri而不是基本Uri。

我将所有的代码都保存在一个razor.cs文件中,所以我可以像这样从后台注入NavigationManager:

[Inject] public NavigationManager Navigation { get; set; } 

导航.Uri产生: https://localhost:5001/nail-square-singel-shear-timber-timber

所以要获取页面Uri,只需按照以下方式操作:

Navigation.Uri.Replace(Navigation.BaseUri,"")

以上结果为:钉-方形-单剪-木材-木材。

这个方法 NavigationManager.ToBaseRelativePath(string uri) 的目的是什么。 - T.Trassoudaine

4

在页面或组件中连接OnLocationChanged 事件没有用,因为它们会按需加载和处理。

你应该在app.cshtml中注册此事件,因为它不会被处理掉。


3
您需要监听 IUriHelper 的 LocationChange 事件,该事件会触发您想要的功能。例如:
@using Microsoft.AspNetCore.Blazor.Components
@using Microsoft.Extensions.Logging
@inject Microsoft.AspNetCore.Blazor.Services.IUriHelper UriHelper
@inject ILogger<NavItem> logger

<li class="m-menu__item @(Active ? "m-menu__item--active" : "")">
    <a href=@Url class="m-menu__link ">
        <span class="m-menu__item-here"></span>
        <i class="m-menu__link-icon @Icon"></i>
        <span class="m-menu__link-text">@Text</span>
    </a>
</li>

@functions {
    protected override void OnInit()
    {
        UriHelper.OnLocationChanged += OnLocationChanges;
    }
    [Parameter]
    private string Url { get; set; }
    [Parameter]
    private string Icon { get; set; }
    [Parameter]
    private string Text { get; set; }
    private bool Active = false;
    private void OnLocationChanges(object sender, string newLocation)
    {
        bool active = newLocation.Contains(Url);
        if(active != Active) //Only re-render the components that need it
        {
            Active = active;
            StateHasChanged();
            logger.LogInformation("Location Change To:" + newLocation);
        }
    }
}

这个 UriHelper.OnLocationChanged 事件有新的参数,导致在 .netCore 3 preview6 中出现错误。应该改为:private void OnLocationChanges(object sender, LocationChangedEventArgs e)。 - Enkode
3
这个答案是针对过时的 Blazor 版本的,请现在使用 NavigationManager。 - sowen

1
在某个地方创建一个类似这样的扩展方法:
namespace YourSolution.YourProject
{
    public static class NavigationManagerExtention
    {
        public static string Page(this NavigationManager navigation)
        {
            return navigation.Uri.Substring(navigation.BaseUri.Length - 1);
        }
    }
}

要获取URL的页面部分,只需调用_nav.Page()

示例:

  • 对于example.com/home,它返回/home
  • 对于example.com/,它返回/

如果您不需要斜杠字符(/),请替换

return navigation.Uri.Substring(navigation.BaseUri.Length - 1);

使用

return navigation.Uri.Substring(navigation.BaseUri.Length);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接