React Router v6如何实现单页内所有路由组件一次性渲染可滚动展示
实现方案
你要做的是长滚动式单页站点,React Router 默认的 <Routes> 组件逻辑就是仅渲染和当前路径匹配的单个 <Route> 组件,完全不符合你要同时渲染所有路由对应组件的需求,直接放弃用 <Routes> 做渲染逻辑即可,改造步骤如下:
- 改造
App.jsx,直接按顺序渲染所有页面组件,不需要<Routes>匹配
// App.jsx import { BrowserRouter, useLocation } from 'react-router-dom' import { useEffect } from 'react' import Home from './Home' import About from './About' import NavBar from './NavBar' function AppContent() { const location = useLocation() // 刷新/首次加载时自动滚动到对应路径的模块位置 useEffect(() => { const targetId = location.pathname.slice(1) const targetEl = document.getElementById(targetId) targetEl?.scrollIntoView() }, [location]) return ( <> <NavBar /> {/* 所有页面组件按顺序渲染,给每个模块加对应id方便锚点定位 */} <Home id="home" /> <About id="about" /> </> ) } function App() { return ( <BrowserRouter> <AppContent /> </BrowserRouter> ) } export default App
注意:你原来写的
component是 React Router v5 的写法,v6 版本的<Route>已经统一用element属性传组件,这里因为不需要路由匹配渲染,所以直接不用写<Route>即可。
- 改造
NavBar.jsx,让点击导航时跳转路径同时滚动到对应模块
// NavBar.jsx import { Link, useNavigate } from 'react-router-dom' function NavBar() { const navigate = useNavigate() const handleNavClick = (path, id) => { // 同步更新浏览器地址栏路径 navigate(path) // 平滑滚动到对应模块 document.getElementById(id)?.scrollIntoView({ behavior: 'smooth' }) } return ( <nav> <Link to="/home" onClick={(e) => { e.preventDefault() handleNavClick('/home', 'home') }}>Home</Link> <Link to="/about" onClick={(e) => { e.preventDefault() handleNavClick('/about', 'about') }}>About</Link> </nav> ) } export default NavBar
- 可选优化:如果路由数量多,可以把路由配置抽成数组统一维护,避免硬编码组件
// src/routes.js 抽离路由配置 export const routes = [ { path: '/home', id: 'home', element: <Home /> }, { path: '/about', id: 'about', element: <About /> } ] // App.jsx 遍历渲染组件 import { routes } from './routes' function AppContent() { // 省略其他逻辑 return ( <> <NavBar /> {routes.map(route => ( <div key={route.path} id={route.id}> {route.element} </div> ))} </> ) }
内容的提问来源于stack exchange,提问作者kwing25
相关产品推荐
相关产品推荐

