如何为 React Router SPA 实现滚动恢复

Posted

技术标签:

【中文标题】如何为 React Router SPA 实现滚动恢复【英文标题】:How to implement scroll restoration for React Router SPA 【发布时间】:2020-03-05 11:07:53 【问题描述】:

我正在构建一个 React 单页应用程序,我注意到滚动恢复在 Chrome(可能还有其他浏览器)中似乎没有按预期工作。

在 react-router-dom github repo 上,他们有一个页面显示浏览器是 starting to natively handle scrolling 用于单页应用程序,如果 @987654328,其行为将类似于传统的非 SPA 网页@ 设置为 auto

我需要的行为显示在该页面上:

    在导航上向上滚动,这样您就不会启动滚动到的新屏幕 底部。 恢复窗口的滚动位置和溢出 “后退”和“前进”点击(但不是链接点击!)

但我还需要禁用包含选项卡或轮播的路线的行为。

这是Chrome's spec on the issue的链接。

我在 OS X 的 Chrome 版本 78.0.3904.97(官方构建)(64 位)中观察到的内容似乎是我对 history.scrollRestoration manual 设置的期望。也就是说,当我向下滚动页面的一半时,当我点击一个链接时,下一页页面将向下滚动到页面的一半,与上一页相同。

我在各个点检查了history.scrollRestoration,发现它开始并保持auto,默认值,

这里有一点很重要,这来自@TrevorRobinson 的回答“浏览器在滚动恢复时的自动尝试......大多数情况下不适用于单页应用......”好吧......我找到了一致的支持对于history.scrollRestoration,但显然浏览器在实际进行滚动恢复方面很糟糕。然后应该注意here,这会节省我今天的时间。

然后我寻找手动执行此操作的方法,但我不清楚前进的方向。 react-router-scroll 说它与 React Router v4 不兼容,但没有提到 v5,这是本问题的最新版本。那么我应该假设 v5 也不兼容吗?

所以我进一步寻找前进的方向,并找到了这个关于 how to handle scroll restoration with React Router v4 的 SO 答案...我应该假设 与 React Router v5 一起使用吗? 更新:在 v5 中它似乎不适用于我。我尝试了几种配置。我也无法完全使用 React Router v4。我知道它至少还活着,因为它在新页面上滚动到顶部,但历史中的恢复不会发生。

我也得到了react-router-scroll-memory 的工作,但它没有在指定路线上禁用滚动的选项,例如选项卡或轮播所需的内容......我可能只是破解它以使其工作。

我考虑过使用oaf-react-router,但它在文档中没有说明有关禁用某些路线的滚动恢复或滚动到顶部的信息。 编辑:它确实可以处理这个问题,正如我的回答中所述。

有什么我忽略的吗?处理这个问题的标准是什么,因为我不能是唯一需要这个功能的人。看起来我在做一些前卫和实验性的事情,但我只需要我的网站像普通网站一样滚动。

【问题讨论】:

你应该看看Nextjs,他们通过缓存历史实现了这一点。 酷!当我能从这个项目中下来时,我会仔细看看。 【参考方案1】:

一种方法是使用oaf-react-router。使用设置中的shouldHandleAction 选项。该函数通过previousLocationnextLocation 传递,您可以使用它们来确定是否应该重置/恢复滚动,如果不应该返回false

const history = createBrowserHistory();

const settings = 
   shouldHandleAction: (previousLocation, nextLocation) => 
       // Inspect/compare nextLocation and/or previousLocation.
       return false // false if you don't want scroll restoration.
   
;

wrapHistory(history, settings);

oaf-react-router 与 React Router v4 和 v5 一起工作,并处理许多 SPA 路由器不具备的可访问性,因此它可能是目前最完整的解决方案。

奇怪的是,文档没有详细说明此功能。

如果其他人有一个可行的解决方案并且被认为是更标准的解决方案,请在此处提供答案,我会考虑更改所选答案。

【讨论】:

以上是关于如何为 React Router SPA 实现滚动恢复的主要内容,如果未能解决你的问题,请参考以下文章

如何为每个 Material-UI TableRow 添加 <Link> react-router?

如何使 reactjs/flux/react-router spa 同构?

SPA单页面应用router实现

如何为 AWS Elb 后面的 reactJs SPA 重定向 http 到 https?

react-router详细解释

如何为每一行添加单独的滚动,我想在 ag-grid-react 的嵌套级别排序