先说结论
Next.js 提供了一个实验性的配置 scrollRestoration ,将该值设置为 true 即可。
如下:
// next.config.js
module.exports = {
// ...省略其他配置
experimental: {
scrollRestoration: true,
},
};
为什么要有这个配置
首先要知道的是浏览器本来就可以保留之前页面的滚动位置,这是浏览器的默认行为。
但是因为在 Next.js 中进行页面切换时,如果页面所需的数据是异步获取的,会发生页面还没有渲染好浏览器就会恢复滚动位置的问题,如图所示:
与上图相关的 Issue 在这里。这种情况下还可能会破坏页面滚动位置的恢复。所以这里需要手动恢复页面滚动位置。
如何解决
首先设置 history.scrollRestoration 的值为 manual,禁用浏览器的默认行为。
window.history.scrollRestoration = 'manual';
然后就是在触发浏览器路由切换时保存页面的滚动位置,当重新返回时再应该之前保存的位置信息使页面滚动到正确的位置上。
//...其他代码
// 保存滚动位置
sessionStorage.setItem(key, JSON.stringify({ x: window.pageXOffset, y: window.pageYOffset })
//...其他代码
// 页面返回后,滚动到之前的位置
const position = JSON.parse(sessionStorage.getItem(key));
window.scrollTo(position.x, position.y);
//...其他代码
具体实现请查看相关 PR 的源码。