1. 路由用法
1.1 基本用法
import React from "react"
import ReactDOM from "react-dom/client"
import App from "./App"
import { HashRouter } from "react-router-dom"
const root = ReactDOM.createRoot(document.getElementById("root"))
root.render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>
)
import React, { PureComponent } from "react"
import { Route } from "react-router-dom"
import { Link } from "react-router-dom"
import { Routes } from "react-router-dom"
import About from "./pages/About"
import Home from "./pages/Home"
export class App extends PureComponent {
render() {
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
<Link to="/home">首页</Link>
<Link to="/about">关于</Link>
</div>
<hr />
</div>
<div className="content">
{/* 映射关系: path => Component */}
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
<div className="footer">
<hr />
Footer
</div>
</div>
)
}
}
export default App
1.2 Link 与 NavLink 的区别
- NavLink 与 Link 的区别在于前者可以添加类属性,以此来添加样式
- NavLink 会自动添加一个叫 active 的类名
- NavLink 可以自定义类名
// 方式一
<NavLink to="/home">
首页
</NavLink>
<NavLink to="/about">
关于
</NavLink>
// style.css
.nav .active {
color: red
}
// 方式二
<NavLink to="/home" style={({ isActive }) => ({ color: isActive ? "blue" : "" })}>
首页
</NavLink>
<NavLink to="/about" style={({ isActive }) => ({ color: isActive ? "blue" : "" })}>
关于
</NavLink>
// 方式三
<NavLink to="/home" className={({ isActive }) => (isActive ? "link-active" : "")}>
首页
</NavLink>
<NavLink to="/about" className={({ isActive }) => (isActive ? "link-active" : "")}>
关于
</NavLink>
1.3 Navigate 导航
1.3.1 判断是否登录
import React, { PureComponent } from "react"
import { Navigate } from "react-router-dom"
export class Login extends PureComponent {
constructor(props) {
super(props)
this.state = {
isLogin: true
}
}
render() {
const { isLogin } = this.state
return (
<div>
<button onClick={e => this.setState({ isLogin: !isLogin })}>登录</button>
{isLogin ? <h1>Login Page</h1> : <Navigate to="/home" />}
</div>
)
}
}
export default Login
1.3.2 重定向
<Route path="/" element={<Navigate to="/home" />} />
1.3.3 错误页面
<Route path="*" element={<NotFound />} />
1.4 路由嵌套
- 直接在对应的 Route 路由里面添加对应的子路由就可以,而在之前的版本中路由很分散,不易于管理
import React, { PureComponent } from "react"
import { Outlet } from "react-router-dom"
import { Link } from "react-router-dom"
export class Home extends PureComponent {
render() {
return (
<div>
<h1>Home Page</h1>
<Link to="/home/recommend">推荐</Link>
<Link to="/home/ranking">排行榜</Link>
<Outlet />
</div>
)
}
}
export default Home
<Route path="/home" element={<Home />}>
<Route path="/home" element={<Navigate to="/home/recommend" />} />
<Route path="/home/recommend" element={<HomeRecommend />} />
<Route path="/home/ranking" element={<HomeRanking />} />
</Route>
1.5 手动路由
1.5.1 函数组件
export function App(props) {
const navigate = useNavigate()
function navigateTo(path) {
console.log(path)
navigate(path)
}
return (
<div className="app">
<div className="header">
<span>Header</span>
<div className="nav">
<Link to="/home">首页</Link>
<Link to="/about">关于</Link>
<Link to="/login">登录</Link>
<button onClick={e => navigateTo("/profile")}>个人信息</button>
<span onClick={e => navigateTo("/order")}>订单</span>
</div>
<hr />
</div>
<div className="content">
{/* 映射关系: path => Component */}
<Routes>
<Route path="/" element={<Navigate to="/home" />} />
<Route path="/home" element={<Home />}>
<Route path="/home" element={<Navigate to="/home/recommend" />} />
<Route path="/home/recommend" element={<HomeRecommend />} />
<Route path="/home/ranking" element={<HomeRanking />} />
</Route>
<Route path="/about" element={<About />} />
<Route path="/login" element={<Login />} />
<Route path="/profile" element={<Profile />} />
<Route path="/order" element={<Order />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
<div className="footer">
<hr />
Footer
</div>
</div>
)
}
1.5.2 类组件
import { useNavigate } from "react-router-dom"
export function withRouter(WrapperComponent) {
return function (props) {
const navigate = useNavigate()
const router = { navigate }
return <WrapperComponent {...props} router={router} />
}
}
import React, { PureComponent } from "react"
import { Outlet } from "react-router-dom"
import { Link } from "react-router-dom"
import { withRouter } from "../hoc"
export class Home extends PureComponent {
navigate(path) {
const { navigate } = this.props.router
navigate(path)
}
render() {
return (
<div>
<h1>Home Page</h1>
<Link to="/home/recommend">推荐</Link>
<Link to="/home/ranking">排行榜</Link>
<button onClick={e => this.navigate("/home/songmenu")}>歌单信息</button>
<Outlet />
</div>
)
}
}
export default withRouter(Home)
1.6 使用路由获取参数
1.6.1 useParams
<Route path="/detail/:id" element={<Detail />} />
...
navigateToDetail(id) {
const { navigate } = this.props.router
navigate("/detail/" + id)
console.log(id)
}
render() {
const { menuList } = this.state
return (
<div>
<h1>HomeSongMenu Page</h1>
<ul>
{menuList.map(list => (
<li key={list.id} onClick={e => this.navigateToDetail(list.id)}>
{list.name}
</li>
))}
</ul>
</div>
)
}
export default withRouter(HomeSongMenu)
import { useParams } from "react-router-dom"
import { useNavigate } from "react-router-dom"
export function withRouter(WrapperComponent) {
return function (props) {
const navigate = useNavigate()
const params = useParams()
const router = { navigate }
return <WrapperComponent {...props} router={router} params={params} />
}
}
import React, { PureComponent } from "react"
import { withRouter } from "../hoc"
export class Detail extends PureComponent {
render() {
const { params } = this.props
return (
<div>
<h1>Detail Page</h1>
<div>id: {params.id}</div>
</div>
)
}
}
export default withRouter(Detail)
1.6.2 查询字符串的参数
import { useLocation } from "react-router-dom"
import { useSearchParams } from "react-router-dom"
import { useParams } from "react-router-dom"
import { useNavigate } from "react-router-dom"
export function withRouter(WrapperComponent) {
return function (props) {
const navigate = useNavigate()
const params = useParams()
const location = useLocation()
const [searchParams] = useSearchParams()
const query = Object.fromEntries(searchParams)
const router = { navigate, params, query }
return <WrapperComponent {...props} router={router} />
}
}
<Link to="/user?name=lwz&age=18">用户</Link>
<Route path="/user" element={<User />} />
import React, { PureComponent } from "react"
import { withRouter } from "../hoc"
export class User extends PureComponent {
render() {
const { query } = this.props.router
return (
<div>
<h1>
User Page: {query.name} - {query.age}
</h1>
</div>
)
}
}
export default withRouter(User)
1.7 路由配置文件
const routes = [
{
path: "/",
element: <Navigate to="/home" />
},
{
path: "/home",
element: <Home />,
children: [
{
path: "/home/recommend",
element: <HomeRecommend />
},
{
path: "/home/ranking",
element: <HomeRanking />
}
]
},
{
path: "*",
element: <NotFound />
}
]
export default routes
import { useRoutes } from "react-router-dom"
import routes from "./router"
{useRoutes(routes)}
1.8 Router-页面的懒加载和Suspence
const Detail = React.lazy(() => import("../pages/Detail"))
const User = React.lazy(() => import("../pages/User"))
...
root.render(
<React.StrictMode>
<HashRouter>
<Suspense fallback={<h3>Loading...</h3>}>
<App />
</Suspense>
</HashRouter>
</React.StrictMode>
)