Skip to main content

react-router-dom

react使用react-router-dom作为路由, react-router-dom的路由是由html5演化来的,它支持2种路由模式:

  • BrowserRouter
  • HashRouter

由于react版本的更新, react-router-dom的api也会发生相应的变化

当前环境

  • react: ^18.2.0
  • react-router-dom: ^6.14.2

一个简单的路由

1, 在使用路由之前需要先安装路由:

npm i react-router-dom -S

2,定义路由

需要注意的是:react-router-dom是按路由定义顺序匹配的

import React from 'react'
import A from './components/A'
import B from './components/B'
import C from './components/C'
import Page404 from './components/Page404'
import { Routes, Route } from 'react-router-dom'

function App() {
return (
<>
<Routes>
<Route path='/a' element={<A/>}/>
<Route path='/b' element={<B/>}/>
<Route path='/c' element={<C/>}/>
<Route path='*' element={<Page404/>}/>
</Routes>
</>
)
}

export default App

3, 挂载路由 - 将路由挂载到根节点

import { BrowserRouter } from "react-router-dom"

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);

接着,路由就可以正常使用了,是不是很简单~

来看下面的效果:

添加Header让导航更方便

App.js:

import React from 'react'
import A from './components/A'
import B from './components/B'
import C from './components/C'
import { Routes,Route } from 'react-router-dom'
import Header from './components/Header'

function App() {
return (
<>
<Header/>
<Routes>
<Route path='/a' element={<A/>}/>
<Route path='/b' element={<B/>}/>
<Route path='/c' element={<C/>}/>
</Routes>
</>
)
}

export default App

components/Header/index.js:

import React, { memo } from 'react'
import { HeaderWrapper } from './style'
import { NavLink } from 'react-router-dom'
import { UUID } from 'uuidjs'

const navBars = [
{
url: "/a",
text: "A"
},
{
url: "/b",
text: "B"
},
{
url: "/c",
text: "C"
},
]

const Header = memo(() => {
return (
<HeaderWrapper>
<ul>
{
navBars.map(item=>{
return (
<li key={UUID.generate()}>
<NavLink to={item.url}>{item.text}</NavLink>
</li>
)
})
}
</ul>
</HeaderWrapper>
)
})

export default Header

components/Header/style.js:

import styled from "styled-components";

export const HeaderWrapper = styled.div`
ul {
display: flex;
}
ul li {
list-style: none;
margin-right: 10px;
}
ul li a {
text-decoration: none;
}

ul li a.active{
background: red;
color:#ccc;
}
`

来看看分别点击A、 B、 C的效果:

路由简化

react18提供了一个useRoutes的hook,你可以把配置传给这个hook,从而告别Routes, Route的编写(仔细观察,提取的正是Route组件的属性)

routes/index.js:

import React from "react";
import A from "../components/A";
import B from "../components/B";
import C from "../components/C";

const routes = [
{
path:"/a",
element: <A/>
},
{
path:"/a",
element: <A/>
},
{
path:"/b",
element: <B/>
},
{
path:"/c",
element: <C/>
}
]

export default routes

然后在App.js中使用这个hook就可以了

import React from 'react'
import { useRoutes } from 'react-router-dom'
import Header from './components/Header'
import routes from './routes'

function App() {
return (
<>
<Header/>
{useRoutes(routes)}
</>
)
}

export default App

路由重定向<Navgate to='/a/b/xx' />

需要注意的是to接收的是个字符串path

routes/index.js:

import React from "react";
import A from "../components/A";
import B from "../components/B";
import C from "../components/C";
import { Navigate } from "react-router-dom";

const routes = [
{
path:"/",
element: <Navigate to='/a' />
},
{
path:"/a",
element: <A/>
},
{
path:"/a",
element: <A/>
},
{
path:"/b",
element: <B/>
},
{
path:"/c",
element: <C/>
}
]

export default routes

路由懒加载

routes/index.js:

import React, { Suspense, memo } from "react";
import { Navigate } from "react-router-dom";
import C from "../components/C";
//lazy load
const A = React.lazy(()=>import("../components/A"))
const B = React.lazy(()=>import("../components/B"))

const Loading = memo(()=>{
return <div>loading...</div>
})

const routes = [
{
path:"/",
element: <Navigate to='/a' />
},
{
path:"/a",
element: (
<Suspense fallback={<Loading/>}>
<A/>
</Suspense>
)
},
{
path:"/b",
element: (
<Suspense fallback={<Loading/>}>
<B/>
</Suspense>
)
},
{
path:"/c",
element: <C/>
}
]

export default routes
  • <Link to='/some/pth'>home</Link>: 相当于a标签,但是Link不会刷新浏览器
  • <NavLink to='/some/pth' />news</NavLink>: NavLink是Link的升级版,当匹配上此路由时,会自动往组件上挂载一个名曰active的class,所以用来做navbar再合适不过了. 如果你希望active在不同组件中拥有不同的style,直接在当前组件中重写active样式即可.