滚动回溯
在早版本的 react-router 中,我们提供了开箱即用的滚动回溯,从那时候开始用户们就一直在要求它。希望本文能够让你获得你需要的信息!
浏览器对 history.pushState 会以普通浏览器导航相同的方式自行处理滚动恢复。它已经可以在 chrome 中使用,而且非常棒。滚动回溯标准
由于浏览器开始处理“默认情况”,并且应用程序具有不同的滚动需求(例如本网站!),因此我们不提供默认滚动管理功能。本指南应帮助您实现任何滚动需求。
滚动到顶部
大多数时候,您需要的只是“滚动到顶部”,因为您的内容页面很长,导航到该页面时,页面会一直向下滚动。这很容易处理。 我们会使用一个<ScrollToTop>
组件,在每次导航时向上滚动窗口:
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
export default function ScrollToTop() {
const { pathname } = useLocation()
useEffect(() => {
window.scrollTo(0, 0)
}, [pathname])
return null
}
如果你还没有开始使用 react 16.8+,你可以使用:
import React from 'react'
import { withRouter } from 'react-router-dom'
class ScrollToTop extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.location.pathname !== prevProps.location.pathname) {
window.scrollTo(0, 0)
}
}
render() {
return null
}
}
export default withRouter(ScrollToTop)
并且在路由前面渲染这个组件:
function App() {
return (
<Router>
<ScrollToTop />
<App />
</Router>
)
}
如果你在路由中有 tab 选项卡,你可能不希望每次切换的时候都滚动到顶部,这时候你可能需要一个<ScrollToTopOnMount>
组件:
import { useEffect } from 'react'
function ScrollToTopOnMount() {
useEffect(() => {
window.scrollTo(0, 0)
}, [])
return null
}
// Render this somewhere using:
// <Route path="..." children={<LongContent />} />
function LongContent() {
return (
<div>
<ScrollToTopOnMount />
<h1>Here is my long content page</h1>
<p>...</p>
</div>
)
}
如果你还没有开始使用 react 16.8+,你可以使用:
import React from 'react'
class ScrollToTopOnMount extends React.Component {
componentDidMount() {
window.scrollTo(0, 0)
}
render() {
return null
}
}
// Render this somewhere using:
// <Route path="..." children={<LongContent />} />
class LongContent extends React.Component {
render() {
return (
<div>
<ScrollToTopOnMount />
<h1>Here is my long content page</h1>
<p>...</p>
</div>
)
}
}
通用解决方案
对于通用解决方案(主流浏览器们已经开始原生实现),我们谈论的是两件事:
- 向上滚动导航,这样就不会启动滚动到底部的新屏幕
- 恢复窗口的滚动位置和“后退”和“前进”单击上的溢出元素(但不单击“链接”单击!)
对于这类情况,我们可能希望提供一个通用 API:
<Router>
<ScrollRestoration>
<div>
<h1>App</h1>
<RestoredScroll id="bunny">
<div style={{ height: '200px', overflow: 'auto' }}>I will overflow</div>
</RestoredScroll>
</div>
</ScrollRestoration>
</Router>
首先,ScrollRestoration 将导航窗口向上滚动。其次,它将 location.key 用于将窗口滚动位置和 RestoredScroll 组件的滚动位置保存到 sessionStorage。然后,当 ScrollRestoration 或 RestoredScroll mount 时,他们可以从 sessionsStorage 查找位置。棘手的部分是为不希望管理窗口滚动的情况定义“退出” API。例如,如果你有一些标签导航浮动你可能你的网页里面的内容不想要滚动到顶部(标签可能被滚出视!)。当我们得知 Chrome 现在可以为我们管理滚动位置,并意识到不同的应用程序将具有不同的滚动需求时,我们有点失去了我们需要提供某些东西的信念,尤其是当人们只想滚动到顶部时(您可以直接将其直接添加到您的应用中)。基于此,我们不再有足够的力气自己完成工作(就像您一样,我们的时间有限!)。但是,我们很乐意为任何愿意实施通用解决方案的人提供帮助。一个可靠的解决方案甚至可以存在于项目中。如果您开始使用它,请与我们联系:)