React+Material UI项目如何实现Grid内组件锚点跳转而非跳独立页
解决方案
问题根源
你当前的路由配置将/about、/resume指向了独立的组件页面,所以点击Link后自然会跳转到新页面;同时没有给页内的对应模块加锚点标识、也没有配置滚动逻辑,因此无法实现页内跳转。你把所有组件放在Grid中做布局是完全符合单页应用开发规范的,不存在结构不合理的问题。
调整步骤
1. 修正App.js路由配置
因为所有内容模块都整合在MainView中,不需要给About、Resume配置独立路由,调整后代码如下:
import React from 'react'; import { BrowserRouter, Switch, Route } from "react-router-dom"; import MainView from './components/MainView'; function App() { return ( <BrowserRouter> <Switch> <Route path='/' component={MainView} /> </Switch> </BrowserRouter> ) } export default App;
2. 给页内模块添加锚点标识
在MainView中给对应模块的外层Grid添加id作为锚点:
import React from 'react'; import Grid from '@material-ui/core/Grid'; import Welcome from './Welcome'; import About from './About'; import Resume from './Resume'; function MainView() { return ( <div> <Grid container spacing={3}> <Grid item xs={12}> <Welcome /> </Grid> <Grid item xs={12} id="about"> <About /> </Grid> <Grid item xs={12} id="resume"> <Resume /> </Grid> </Grid> </div> ); } export default MainView;
3. 调整Menu组件实现滚动跳转
可以根据需求选择以下两种实现方式:
方式1:原生锚点跳转(最简实现)
不需要依赖react-router的路由能力,直接用a标签实现,支持平滑滚动:
import React from 'react'; function Menu() { return ( <div> <a href="#about">About</a> <a href="#resume">Resume</a> </div> ); } export default Menu;
如果需要平滑滚动效果,在全局CSS中添加以下配置即可:
html { scroll-behavior: smooth; }
方式2:带路由状态的跳转(支持保存链接、前进后退)
如果需要点击后URL同步变化、用户可以保存链接直接访问对应位置,就用这种方式:
首先修改Menu组件:
import React from 'react'; import { Link } from 'react-router-dom'; function Menu() { return ( <div> <Link to="/#about">About</Link> <Link to="/#resume">Resume</Link> </div> ); } export default Menu;
然后在MainView中添加监听hash变化自动滚动的逻辑:
import React, { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import Grid from '@material-ui/core/Grid'; import Welcome from './Welcome'; import About from './About'; import Resume from './Resume'; function MainView() { const location = useLocation(); // 监听路由hash变化,自动滚动到对应位置 useEffect(() => { if (location.hash) { const targetEl = document.querySelector(location.hash); if (targetEl) { targetEl.scrollIntoView({ behavior: 'smooth' }); } } }, [location]); return ( <div> <Grid container spacing={3}> <Grid item xs={12}> <Welcome /> </Grid> <Grid item xs={12} id="about"> <About /> </Grid> <Grid item xs={12} id="resume"> <Resume /> </Grid> </Grid> </div> ); } export default MainView;
疑问解答
- 能不能直接为Grid内的组件添加跳转链接?可以,上述方案就是直接给Grid组件加id作为锚点,完全可以正常工作。
- 将所有组件放在Grid中是否不符合带可链接组件的单页应用开发要求?完全符合,Grid只是Material-UI提供的布局组件,只要你的业务需求是所有内容在同一页展示,用Grid排版没有任何问题,也不影响锚点、路由功能的实现。
内容的提问来源于stack exchange,提问作者natpas
相关产品推荐
相关产品推荐

