使用锚点导航到Blazor中的命名元素。

huangapple go评论72阅读模式
英文:

Routing to named element in Blazor (use anchor to navigate to specific element)

问题

我无法使用HTML锚点在Blazor Server中导航到页面的特定HTML元素。例如:

@page "/test"

<nav>
    <!-- 我尝试过的一种版本 -->
    <a href="#section2">Section2</a>

    <!-- 我尝试过的另一种版本 -->
    <NavLink href="#section2">Section2</NavLink>
</nav>

@* ... *@


<h2 id="section2">这是第2部分。</h2>
@* ... *@

当我点击Section2的链接时,我会被重定向到路由http://localhost:5000/test#section2,但会位于页面顶部。在我看来,浏览器应该滚动到由Element Selector指定的正确元素,但它无法实现。

在Blazor中需要以特殊的方式完成吗?

我在.NET 6中使用Blazor 6和Visual Studio 2022(版本:17.0.2)。

英文:

I cannot use an HTML anchor to navigate to a specific HTML element of a page in the Blazor Server. For example:

@page &quot;/test&quot;

&lt;nav&gt;
    &lt;!-- One version I&#39;ve tried --&gt;
    &lt;a href=&quot;#section2&quot;&gt;Section2&lt;/a&gt;

    &lt;!-- Another version I&#39;ve tried --&gt;
    &lt;NavLink href=&quot;#section2&quot;&gt;Section2&lt;/NavLink&gt;    
&lt;/nav&gt;

@* ... *@


&lt;h2 id=&quot;section2&quot;&gt;It&#39;s Section2.&lt;/h2&gt;
@* ... *@

When I click the link to Section2, I get redirected to the route http://localhost:5000/test#section2, however, will be at the top of the page. In my opinion, the browser should scroll down to the proper element, as specified by the Element Selector, but it can't.

Does it have to be done in a special way in Blazor?

I use Blazor 6 in .Net6 with Visual Studio 2022 (ver:17.0.2).

答案1

得分: 2

在加载页面后,浏览器会自动滚动到URL片段部分中由其ID标识的元素。当你点击带有href属性为#element-id的锚链接时,它也会执行相同的操作。

对于Blazor服务器端,页面加载行为不起作用,因为在页面加载时该元素尚不存在。

解决方法是使用JavaScript和Razor组件手动创建一个滚动器:

首先,创建一个类似如下的Razor组件:

@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@implements IDisposable
@code {
    protected override void OnInitialized()
    {
        NavigationManager.LocationChanged += OnLocationChanged;
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await ScrollToFragment();
    }

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

    private async void OnLocationChanged(object sender, LocationChangedEventArgs e)
    {
        await ScrollToFragment();
    }

    private async Task ScrollToFragment()
    {
        var uri = new Uri(NavigationManager.Uri, UriKind.Absolute);
        var fragment = uri.Fragment;
        if (fragment.StartsWith('#'))
        {
            // 处理文本片段(https://example.org/#test:~:text=foo)
            // https://github.com/WICG/scroll-to-text-fragment/
            var elementId = fragment.Substring(1);
            var index = elementId.IndexOf(":~:", StringComparison.Ordinal);
            if (index > 0)
            {
                elementId = elementId.Substring(0, index);
            }

            if (!string.IsNullOrEmpty(elementId))
            {
                await JSRuntime.InvokeVoidAsync("BlazorScrollToId", elementId);
            }
        }
    }
}

然后,在Blazor脚本渲染之前的某处添加以下JavaScript代码。你可以使用 :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定