Blazor 在同一组件中更改 Url,但保存滚动位置而不闪烁

问题描述 投票:0回答:4

我有一个具有页面属性的组件,该组件与交付平台中选定的父类别和子类别的参数相匹配。

@page "/{Alias}/speisekarte"
@page "/{Alias}/speisekarte/{CategoryText}"
@page "/{Alias}/speisekarte/{CategoryText}/{SubCategoryText}"

这里我们有一个父类别“Pizza”和子类别“MyPizza”的示例:

https://v7pizzaboy.gastroblitz.de/duesseldorf-derendorf/speisekarte/pizza/mypizza

现在的问题是,当通过单击更改类别时,切换到同一组件“MenuPage.razor”的新 Url 时,它总是跳到最开头。

    <div class="swiper-slide swiper-slide-active" style="width: 136.25px;"
        @onclick="(() => GotoCategory(category.Permlink))">
        <a class="@(category == CurrentParentCategory ? "active" : "")" href="#" @onclick:preventDefault>
             <img src="/img/@category.NavigationIcon" height="36" alt="Aktion" class="">
             <span>@category.Name</span>
        </a>
    </div>

无论我使用带有目标链接的 href 还是 NavigationManager:

    public void GotoCategory(string permLink)
    {
        var url = $"/{My.Store.PrimaryAlias}/speisekarte/{permLink}";
        NavigationManager.NavigateTo(url);
    }

您可以在页面上尝试一下(上面的链接):

  1. 向下滚动
  2. 然后点击导航链接

问题是如何更改给定的数据和 url,但保持相同的滚动位置以获得良好的用户体验?

routes blazor
4个回答
1
投票

理论上,您可以以某种方式存储滚动位置(为此您需要 JavaScript 互操作)。 但是,如果数据也发生变化,则使用先前的滚动就没有意义了。

另一方面,如果相同的位置对于更改的数据也有意义,那么最好的解决方案可能是避免离开页面。您可以通过使用回调来更改绑定页面的数据来实现此目的。也就是说,您使用点击事件在同一页面上加载不同的数据,从而仅更改页面中需要更改的部分。

这肯定会给用户带来更好的体验和更好的性能,因为您不会刷新整个页面,而只会刷新某些部分,并且您将避免导航。作为副作用,页面上的其他状态信息也不会丢失。


0
投票

NavigateTo 函数很可能导致页面重新初始化? 无论如何,我会通过添加一个静态变量来保存浏览器的滚动位置来解决这个问题。在导航之前进行设置。然后,在 OnAfterRender 重写中,我将调用 Javascript 互操作 (IJSRuntime) 将容器滚动回到上一个位置。


0
投票

您可以通过多种方式解决这个问题;

或者,如果您想避免使用 JavaScript,您可以在链接中包含锚标记。


0
投票

我的解决方案是使用

pushState

window.history.pushState({page: "another"}, "another page", "example.html");

所以,我创建了一个辅助类

using Microsoft.JSInterop;
using System.Threading.Tasks;

public static class JSRuntimeExtensions
{
    public async static Task ChangeRouteWithoutReload(this IJSRuntime js, string newRoute, string pageName)
    {
        await js.InvokeAsync<string>("window.history.pushState", new { page = pageName }, pageName, newRoute);
    }
}

可以这样使用

[Inject]
protected IJSRuntime JS { get; set; } = null;

private async Task ChangeRoute()
{
    await JS.ChangeRouteWithoutReload("/new-route", "New Page Name");
}
© www.soinside.com 2019 - 2024. All rights reserved.