单击Blazor中的顶部导航链接,滚动到页面的特定部分

问题描述 投票:3回答:2

如何在Blazor中简单地“跳转”到已加载页面的一部分?在HTML中像这样:

<a href="#contact">Contact us</a>
...
<section id="contact">

理想情况下,我也希望顺利向下滚动到此部分。以为我会尝试用CSS解决这个问题,但也许不可能?

c# html css blazor
2个回答
4
投票

你需要的是Blazor的散列路线功能。但是,唉,还没有这样的功能。我建议您使用JSIterop来执行此任务:创建执行导航的JavaScript,并将其传递给ElementRef对象。

希望这可以帮助...

编辑:以下是我在Github找到的最佳解决方案的改编...

通常,当您单击要联系的链接时,您将被重定向到路线http://localhost:5000/mypage#contact,但将位于页面顶部。路径的片段不用于选择特定的HTML元素。

当前的解决方法是编写解释URL的显式代码。在上面的例子中,我们可以使用一点JavaScript,然后从我们的Blazor代码中调用它:

mypage.cshtml:

         @page "/mypage"
    @inject Microsoft.AspNetCore.Components.Services.IUriHelper UriHelper

    <nav>

        <a href="#contact">contact</a>


    </nav>


    <section>
        <h2 id="contact">contact</h2>

    </section>


@functions {
    protected override void OnInit()
    {
        NavigateToElement();
        UriHelper.OnLocationChanged += OnLocationChanges;
    }

    private void OnLocationChanges(object sender, string location) => NavigateToElement();

    private void NavigateToElement()
    {
        var url = UriHelper.GetAbsoluteUri();
        var fragment = new Uri(url).Fragment;

        if(string.IsNullOrEmpty(fragment))
        {
            return;
        }

        var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

        if(string.IsNullOrEmpty(elementId))
        {
            return;
        }

        ScrollToElementId(elementId);
    }

    private static bool ScrollToElementId(string elementId)
    {
        return JSRuntime.Current.InvokeAsync<bool>("scrollToElementId", elementId).GetAwaiter().GetResult();
    }
}

index.html的:

<script>
        window.scrollToElementId = (elementId) => {
            console.info('scrolling to element', elementId);
            var element = document.getElementById(elementId);
            if(!element)
            {
                console.warn('element was not found', elementId);
                return false;
            }
            element.scrollIntoView();
            return true;
        }
</script>

注意:如果你使用Blazor版本.9.0,你应该注入IJSRuntime请告诉我这个解决方案是否适合你...


0
投票

与Issac的答案相同的答案,但需要更改一些代码。

我发现主要的问题是你需要它是异步的。 @johajan

@inject IJSRuntime JSRuntime

...

@functions {
protected override async Task OnInitAsync()
{
    await base.OnInitAsync();
    //NavigateToElement();
    UriHelper.OnLocationChanged += OnLocationChanges;
}

private async Task OnLocationChanges(object sender, string location) => await NavigateToElement();

private async Task NavigateToElement()
{
    var url = UriHelper.GetAbsoluteUri();
    var fragment = new Uri(url).Fragment;

    if(string.IsNullOrEmpty(fragment))
    {
        return;
    }

    var elementId = fragment.StartsWith("#") ? fragment.Substring(1) : fragment;

    if(string.IsNullOrEmpty(elementId))
    {
        return;
    }

    await ScrollToElementId(elementId);
}

private Task<bool> ScrollToElementId(string elementId)
{
    return JSRuntime.InvokeAsync<bool>("scrollToElementId", elementId);
}

}

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