导航到新页面后,停止到达路由器向下滚动页面

Eva*_*nss 10 reactjs reach-router

当我导航到新页面时,“到达路由器”向下滚动到页面内容的标题上方(如果内容足够长)。我假设这是为了可访问性,但对于我的应用程序不是必需的,并且实际上是很麻烦的。可以禁用此行为吗?

请注意,我所说的是“到达路由器”而不是“反应路由器”。

到达路由器

Vin*_*ius 12

尝试使用<Router primary={false}>哪些将不关注路线组件。

https://reach.tech/router/api/路由器

主要:布尔

默认为true。主路由器将专注于位置转换。如果为false,将不会管理焦点。这对于呈现为辅助对象,标头,面包屑等的路由器很有用,但对于主要内容却不可用。

警告:如果您担心破坏可访问性,请参阅以下答案:https : //stackoverflow.com/a/56996986/428780

  • 无济于事,仍然滚动到一些奇怪的偏移量 (2认同)

dav*_*wil 10

在解决 OP 的问题时,这里的最佳答案可能不是大多数人想要的解决方案,因为它关闭了 Reach 路由器最重要的可访问性功能。

事实上,Reach 路由器将匹配的内容集中在<Route>路由更改上是出于可访问性的原因- 因此,当您导航到新页面时,屏幕阅读器等可以定向到新更新的相关内容。

它用于HTMLElement.focus()执行此操作 -请参阅此处的 MDN 文档

问题是默认情况下,此函数会滚动到被聚焦的元素。这里一个preventScroll可以用来关闭该行为的说法,但它的浏览器的支持并不好,也不管,关爱路由器不使用它。

设置primary={false}为您可能拥有的任何嵌套 关闭此行为<Router>- 它打算false在您的主要(主要)上设置<Router>- 因此得名。

因此,设置primary={false}您的 primary <Router>,正如最佳答案所暗示的那样,在它停止滚动行为的意义上“有效” ,但它通过简单地完全关闭聚焦行为来实现这一点,这破坏了可访问性功能。正如我所说,如果您这样做,您首先会破坏使用 Reach Router 的主要原因之一。

那么,有什么解决办法呢?

基本上,这种副作用HTMLElement.focus()- 滚动到焦点元素 -似乎是不可避免的。因此,如果您想要可访问性功能,则必须采用滚动行为。

但话虽如此,可能有一种解决方法。如果您window.scrollTo(0, 0)在每次路线更改时手动滚动到页面顶部,我相信这不会从可访问性的角度“破坏”聚焦功能,但会从 UX 的角度“修复”滚动行为。

当然,这是一个有点棘手和必要的解决方法,但我认为这是解决此问题的最佳(也许是唯一)解决方案,同时又不破坏可访问性。

这是我如何实施它

class OnRouteChangeWorker extends React.Component {
  componentDidUpdate(prevProps) {
    if (this.props.location.pathname !== prevProps.location.pathname) {
      this.props.action()
    }
  }

  render() {
    return null
  }
}

const OnRouteChange = ({ action }) => (
  {/* 
      Location is an import from @reach/router, 
      provides current location from context 
  */}
  <Location>
    {({ location }) => <OnRouteChangeWorker location={location} action={action} />}
  </Location>
)

const Routes = () => (
  <>
    <Router>
      <LayoutWithHeaderBar path="/">
        <Home path="/" />
        <Foo path="/foo" />
        <Bar path="/bar" />
      </LayoutWithHeaderBar>
    </Router>

    {/* 
        must come *after* <Router> else Reach router will call focus() 
        on the matched route after action is called, undoing the behaviour!
    */}
    <OnRouteChange action={() => { window.scrollTo(0, 0) } />
  </>
)
Run Code Online (Sandbox Code Playgroud)