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