在 react-router 4 中使用锚标签

Posted

技术标签:

【中文标题】在 react-router 4 中使用锚标签【英文标题】:Using anchor tags in react-router 4 【发布时间】:2018-06-21 18:09:54 【问题描述】:

当用户通过锚链接导航到页面时,我希望页面向下滚动到我的锚标记。

我正在使用 react-router 4,我已经定义如下:

导航栏:

export default (props) => 
  const  
    updateModal,
    updateRoute,
   = props
  return(
    <Navbar fluid collapseOnSelect>
      <Nav>
        <NavDropdown eventKey="4" title="Solutions" id="nav-dropdown" noCaret>
          <MenuItem eventKey="4.1">
             <Link to='/solution#ipos'>TESTING ANCHOR</Link>
          </MenuItem>
...

一些路线:

export default class extends Component 
  constructor() 
    super()
    this.state = 
      isLoading: true
    
  
  render() 
    return (
      <Grid className='solutions' fluid>
       <Row className='someClass'>
        <div>
          <h2><a href='ipos' id='ipos'>Ipos morna santos paros</a></h2>
          ...

当我单击导航栏中的锚链接时,我可以在 url 和我的 redux 商店中看到哈希锚标签,它确实导航到新路线,但它不会向下滚动到标签本身。

是否由我来创建滚动功能,或者它应该如何工作?

【问题讨论】:

【参考方案1】:

这是 react 路由器的一个已知问题。 (https://github.com/ReactTraining/react-router/issues/394#issuecomment-220221604)

也有解决办法。 https://www.npmjs.com/package/react-router-hash-link这个包解决了这个问题。

你必须像下面这样使用Hash Link 作为Link

import HashLink as Link from 'react-router-hash-link';

【讨论】:

然而值得注意的是,在这种情况下,只需使用标准的&lt;a&gt; 链接就可以轻松避免这种情况。 React-Router &lt;Link&gt; 不是必需的,因为如果您在同一页面中导航,则无需在此处进行组件操作。因此,标准的&lt;a&gt; 链接可以被认为是最佳解决方案,它不需要安装其他软件包等。但是,如果您需要导航到另一个“页面”上的哈希链接,那么是的,这个软件包就是解决方案。跨度> 【参考方案2】:

要向下滚动到您的锚标记,您需要安装React Router Hash Link,其中:

npm install --save react-router-hash-link

然后导入哈希链接:

import  HashLink as Link  from 'react-router-hash-link';

然后使用Hash Link,例如:

<Link to="/pathLink#yourAnchorTag">Your link text</Link>

在目标组件处,例如:

<div id= "yourAnchorTag">
      <p>Linked to here<p>
</div>

【讨论】:

很难相信在这个包之外还没有更常见的做法。看起来真的很奇怪。 2020 年 2 月报告,这仍然是最好的方法(遗憾) 实际上我什至无法让它按预期运行。这个框架有时会让人大失所望。我有一个永远不会改变的静态 ID 的元素,我要做的就是添加一个 a[href="#myAnchor"] 并滚动到它。如果没有至少 20 行代码,这似乎是不可能的。 这对我来说也很有趣,这个 SO 答案是唯一一个提供了如何编写你链接的东西的例子的答案。谢谢@Adrian【参考方案3】:

如果您只有几个可预测的锚链接,实现正常行为的最简单方法是手动 scrollIntoView() 元素如果您在 Window.location.href 中有预期的锚标记。

class Page extends react.Component 
    componentDidMount() 
        if (this.$ref && location.href.includes('#my-ref')) 
            this.$ref.scrollIntoView(
                // optional params
                behavior: 'smooth',
                block: 'start',
                inline: 'center',
            );
        
    

     render() 
        return (
            // This is the div you want to scroll to
            <div ref=ref => 
                this.$ref = ref;
            >
                Other content
            </div>
        );
    

检查Element.scrollIntoView() 和React refs。

【讨论】:

我搞砸了&lt;a&gt;&lt;Link&gt;&lt;HashLink,但没有一个能正常工作——它们都会刷新页面并可能滚动到正确的位置。这只是通过滚动到正确的位置减去刷新来工作 非常有帮助,谢谢。一个小的修正。参数behaviour 应该是behavior ;)【参考方案4】:

类似于@filippo,但带有 React 钩子和一点 Typescript。

    import React,  Functioncomponent, useEffect, useRef  from 'react';
    import  useLocation  from 'react-router-dom';
    
    const MyFunc: FunctionComponent = () => 
    const myRef = useRef<null | htmlDivElement>(null);
    
        useEffect(() =>  
    if (myRef && location.hash.includes('#my-ref'))  
    
    myRef?.current?.scrollIntoView(
    behavior: 'smooth',
    block: 'start',
    inline: 'center'
    );
    
    
    , [myRef, location.hash]);
    
    return (
    <div> Some stuff before </div>
    <div ref=myRef> Scroll to me </div>
    <div> Some stuff after </div>
    )
    
     
       
        export default MyFunc;

【讨论】:

【参考方案5】:

你可以将一个对象传递给 Link,像这样

<Link
  to=
    pathname: "/courses",
    search: "?sort=name",
    hash: "#the-hash",
    state:  fromDashboard: true 
  
/>

参考。 https://reacttraining.com/react-router/web/api/Link

【讨论】:

这很有帮助。【参考方案6】:

我使用的是 Gatsby,我的解决方案是使用 @reach/router 的形式:

import  navigate  from '@reach/router';
navigate('#some-link');

Link to Gatsby documentation.

【讨论】:

【参考方案7】:

在锚标记中使用散列片段的另一种方法是查询 DOM 并使用scrollIntoView() 作为onClick 事件的一部分。

function handleClick(evt) 
  ...
  document.querySelector('[id="label-input-1"]').scrollIntoView();


...

<a href='' onClick=e => handleClick(e)>Foo</a>

这只是在窗口位置使用哈希地址更新时绕过路由器刷新页面。

【讨论】:

这里的问题是当你切换到另一个路由并且dom还没有完全加载时,函数将找不到锚点,因此不会滚动到它。您将不得不等待组件完全加载 @JonasMerhej - 这不是用于切换路线,而是用于在不刷新路线的情况下滚动到页面上的某个位置。

以上是关于在 react-router 4 中使用锚标签的主要内容,如果未能解决你的问题,请参考以下文章

react-router解决锚点跳转问题

十react-router 4.x的基本配置

使用锚标签链接打开标签?

使用锚的自动布局没有按照我想要的方式布置我的视图?

[react-router] React-Router的<Link>标签和<a>标签有什么区别

关于react-router最新版本的使用