【问题标题】:How to navigate to another page with a smooth scroll on a specific id with react router and react scroll如何使用反应路由器和反应滚动在特定ID上平滑滚动导航到另一个页面
【发布时间】:2020-05-13 15:57:04
【问题描述】:

我正在尝试使导航栏导航到另一个页面并向下滚动到此页面上的某个 id

这是我的 protofolio 的导航栏组件,它有 3 个链接,Projects 应该转到 Home,然后向下滚动到项目部分中的 projects id

import React, { Component } from "react";
import logo from "../../images/logo.png";
import { Link } from "react-router-dom";
import Scroll from "react-scroll";
import "./NavBar.css";
const ScrollLink = Scroll.Link;

class NavBar extends Component {
  render() {
    return (
      <div className="NavBar">
        <Link to="/" className="logo-container">
          <img className="logo" src={logo} alt="Mahboub logo"></img>
        </Link>
        <div className="Nav-links">

          <Link to="/">Home</Link>
          <ScrollLink
            className="navy"
            smooth={true}
            duration={500}
            to="projects"
          >
            projects
          </ScrollLink>

          <Link to="/">Contacts</Link>
        </div>
      </div>
    );
  }
}
export default NavBar;

这是主页中项目部分的项目组件

function Projects() {
  return (
    <div className="Home-Projects">
      <Element id="projects">
        <h1>Projects</h1>
      </Element>
      <div className="Projects-container">
        <ProjectElement />
      </div>
    </div>
  );
}

【问题讨论】:

    标签: javascript reactjs react-router


    【解决方案1】:

    如果“duration”参数对你来说不是很重要,并且你对 Hooks 没有任何问题,我建议如下解决方案。

    • 您摆脱了 Scroll 组件并像这样在 NavBar 中使用来自 RR 的普通链接

      <Link to="/#projects">projects</Link>
      
    • 自 RR v5.1 Hooks was introduced.其中有 useLocation 钩子。在 Projects 组件的最开始插入该钩子,如下所示:

      function Projects() {
      const location = useLocation()
      ...
      

    当您从第 1 页点击链接时,您将获得表单的新位置对象

    
        location = {
            ...
            pathname:"/",
            ...
            hash: "#projects"
        }
    
    
    • useLocation 之后调用useEffect 挂钩,如下所示:
    
        useEffect(()=> {
                if (location.hash) {
                    let elem = document.getElementById(location.hash.slice(1))
                    if (elem) {
                        elem.scrollIntoView({behavior: "smooth"})
                    }
                } else {
                window.scrollTo({top:0,left:0, behavior: "smooth"})
                }
        }, [location,])
    
    

    就是这样。如您所见,如果您的网址中没有散列,您的页面将滚动到顶部。使用[locaton,] 作为useEffect 依赖项可防止页面组件在不是因为位置更改而重新呈现时滚动。

    【讨论】:

    • 这是一个很好的答案!效果很好。谢谢
    • 这非常有效。但我建议添加 html { scroll-behavior: smooth; } 使滚动更流畅
    【解决方案2】:

    我只是在 index.css 中添加这个

    html {
      scroll-behavior: smooth;
    }
    

    还有这个

     <ScrollLink
                className="navy"
                smooth={true}
                duration={500}
                to="projects"
              >
                projects
     </ScrollLink>
    

    成为

     <a href="/#projects">Projects</a>
    

    这又快又简单,而且效果很好

    【讨论】:

    • 我正在尝试做同样的事情,但它不适用于这些
    【解决方案3】:

    对于 next.js

    //https://yourdomain.com/page?scroll=scroll_here <---
    
    import { useEffect } from 'react';
    import { Flex } from '@chakra-ui/react';
    import { useRouter } from 'next/router';
    export default function DecisionAreaFlex(props) {
      const router = useRouter();
      useEffect(() => {
        console.log('router query', router.query.scroll);
        if (router.query.scroll) {
          let elem = document.getElementById(router.query.scroll);
          if (elem) {
            elem.scrollIntoView({ behavior: 'smooth' });
          }
        } else {
          window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
        }
      }, [router]);
    
      return (
        <Flex
          alignSelf="center"
          justifyContent="center"
          alignItems="center"
          mt="15px"
          id={'scroll_here'} // <--- 
        >
          {props.children}
        </Flex>
      );
    }
    

    【讨论】:

      【解决方案4】:

      我创建了一个名为anchor 的查询参数,通过它我可以根据useEffect 控制滚动。

      链接:/about?anchor=capabilities

      页面上应该有平滑滚动的代码:

      const router = useRouter();
      
      useEffect(()=> {
        if (router?.query?.anchor) {
          let elem = document.getElementById(router?.query?.anchor)
          if (elem) {
            elem.scrollIntoView({behavior: "smooth"});
          }
        }
      }, [router?.query?.anchor])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-02
        • 1970-01-01
        • 1970-01-01
        • 2021-06-14
        • 1970-01-01
        • 2020-07-30
        • 1970-01-01
        相关资源
        最近更新 更多