React—12—ReactRouter
一、路由
二、ReactRouter
三、路由的映射配置、跳转
分别是<Routes> <Route> <Link> <NavLink> <Navigate>组件。

匹配到的组件就会渲染在路由表所在的地方,
如果所有的路由都在App.jsx里写,那么子路由就得专门有个占位符了《Outlet了》,不然没法渲染。
import { Routes, Route, Link, Navigate } from 'react-router-dom'; export class App extends PureComponent { render() { return ( <div> <div> 我是头部内容 <Link to="/home">首页</Link> <Link to="/recommend">推荐</Link> <hr /> <hr /> <div style={{ marginBottom: '150px' }}></div> </div>
<div> 我是body部内容 <Routes> <Route path="/" element={<Navigate to="/home" />}></Route> <Route path="/home" element={<Home />}> {/* reactrouter在嵌套路由时,子路由必须使用绝对路径或者相对路径的写法: 绝对路径:子路由必须要带上父路由 相对路径:相对路由的方式写,不要加 / 这点和vue不一样,vuerouter完全根据path匹配。 */} {/* 错误写法,未带上父路由: <Route path="/foo" element={<HomeFoo />}></Route> */} {/* 绝对路径写法:带上父路由/home */} <Route path="/home/foo" element={<HomeFoo />}></Route> {/* 相对路径写法,不加/ */} <Route path="bar" element={<HomeBar />}></Route> </Route> <Route path="/recommend" element={<Recommend />}></Route> <Route path="*" element={<NotFound></NotFound>}></Route> </Routes> </div>
</div> ); } } const mapStateToProps = state => ({ counter: state.counterSlice.counter }); export default connect(mapStateToProps)(App);
四、路由的嵌套
主要是,直接在Route组件里,插入子路由组件。
然后在实际要显示的组件里,使用<Outlet>组件做占位符,vue是<RouterView>组件做占位符。
五、js代码操作路由
刚刚那么多全部都是组件《Link to=’xxx‘》《Navigate to=‘xxx'》跳转,这次我们用js代码来跳转。
5.1函数式组件
import { Routes, Route, Link, Navigate, useNavigate } from 'react-router-dom'; export function App() { const navigate = useNavigate(); return ( <div> <div> 我是头部内容 {/* <Link to="/home">首页</Link> <Link to="/recommend">推荐</Link>
函数式组件想调用非常简单,直接通过hook拿到navigate方法, 然后button直接调用这个方法即可
*/}
<button onClick={e => navigate('/home')}>首页</button> <button onClick={e => navigate('/recommend')}>推荐</button> </div> <div> 我是body部内容 <Routes> <Route path="/recommend" element={<Recommend />}></Route> <Route path="*" element={<NotFound></NotFound>}></Route> </Routes> </div> </div> ); } export default App;
六、路由参数传递
方式一:动态路由参数
这种需要我们在定义的路由时候,就定义一个动态路由,比如/home/:id,那么我们传递/home/foo的时候,将不会走到HomeFoo组件,仍然是Home组件,并且会传递一个参数,
参数可以通过useParams()Hooks取到。
<button onClick={e => navigate('/detail/123')}>详情</button> <Route path="/detail/:id" element={<Detail />}></Route> const params = useParams(); //通过params.id取到动态路由参数的值。
方式二:query参数
这种就是在跳转路由的时候,拼接要给query,比如/home?name=why&age=18,这样当我们跳转到Home组件时,参数可以通过useSearchParams() 取到。
<button onClick={e => navigate('/detail?name=why&age=18')}>详情</button> <Route path="/detail" element={<Detail />}></Route> // 把searchParams转化为query,才是我们需要的 const [searchParams] = useSearchParams(); const query = Object.fromEntries(searchParams);
七、路由的配置文件和懒加载
1.配置文件
我们可以把所有的路由都放在一个配置文件里,然后需要开启前端路由跳转的地方使用useRoutes(路由配置数组)占位即可,当然子路由(即嵌套路由)还是使用《Outlet》组件去占位。
import React from 'react' import Home from '../pages/Home'; // import Recommend from '../pages/Recommend'; import HomeBar from '../pages/HomeBar'; import HomeFoo from '../pages/HomeFoo'; import NotFound from '../pages/NotFound'; import Detail from '../pages/Detail'; import { Navigate } from 'react-router-dom'; const Recommend = React.lazy(() => import('../pages/Recommend')) export const routes = [ { path: '/', element: <Navigate to="/home" /> }, { path: '/home', element: <Home />, children: [ { path: '/home/foo', element: <HomeFoo /> }, { path: '/home/bar', element: <HomeBar /> } ] }, { path: '/recommend', element: <Recommend /> }, // 动态路由参数走这里 { path: '/detail/:id', element: <Detail /> }, // query参数走这里 { path: '/detail', element: <Detail /> }, { path: '*', element: <NotFound /> } ];
App.jsx里
import {routes} from './router' import { useRoutes } from 'react-router-dom'; <div> 我是body部内容 {/* <Routes> <Route path="/" element={<Navigate to="/home" />}></Route> <Route path="/home" element={<Home />}> <Route path="/home/foo" element={<HomeFoo />}></Route> <Route path="bar" element={<HomeBar />}></Route> </Route> <Route path="/recommend" element={<Recommend />}></Route> <Route path="/detail" element={<Detail />}></Route> <Route path="*" element={<NotFound></NotFound>}></Route> </Routes> */} {useRoutes(routes)} </div>
7.2懒加载
有些文件太大,需要调用到的时候,再去加载这个文件。
使用import写法,那么webpack会识别,把这个文件单独打包,并且只有调用到的时候才加载这个文件,加快首屏渲染速度。
但是有个问题,就是如果我们立马调用了recommend组件,但是这个时候recommend文件由于太大了还没加载出来,所以会报错,这个时候我们需要给包裹一个suspense组件做loading,不然会报错。
const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Suspense fallback={<div>组件加载中,请稍后</div>}> <HashRouter> <Provider store={store}> <App /> </Provider> </HashRouter> </Suspense> );