路由
什么是路由
路由维护了URL地址和组件的映射关系,通过这个映射关系,可以根据不同的URL地址,去渲染不同的组件
react-router
安装
npm install react-router-dom
使用
监听模式
无论是Link还是Route都只能放到BrowserRouter和HashRouter中才有效
- 在企业开发中如果不需要兼容低级版本浏览器, 建议使用BrowserRouter
- 如果需要兼容低级版本浏览器, 那么只能使用HashRouter
Link
用于修改URL的资源地址
- to
- 跳转URL
NavLink
功能与Link类似。不同点:可以设置相关样式,例如激活时的高亮
- end
- 精准匹配
- 官网
Routes
- 类似之前版本的Switch
Route
用于维护URL和组件的关系。Route是一个占用组件,将来它会根据匹配到的资源地址渲染对应的组件
- element
- 替代了之前版本的component
- element-Component
outlet
- 类似vue的router-view
Navigate
- 代替了之前的Redirect
import React from "react"
import { BrowserRouter, Routes, Link, Route } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
class App extends React.PureComponent {
render() {
return (
<div id={'app'}>
<BrowserRouter>
{/* <Link to={'/home'} relative='home'>Home</Link>
<Link to={'/home/about'} relative='/home/about'>About</Link> */}
<nav id="sidebar">
<NavLink end to={'/home'}>Home</NavLink>
<NavLink end to={'/about'}>About</NavLink>
<NavLink end to={'/user'}>User</NavLink>
</nav>
{/* <Link to={'/home'}>Home</Link>
<Link to={'/home/about'}>About</Link> */}
<Routes>
<Route path="/" element={<Layout />}>
<Route index path='/home' element={<Home />} />
<Route end path="/about" element={<About />} />
</Route>
<Route path='user' element={<User />} />
<Route path="login" element={<Login />} />
{/* <Route path={'/home'} element={<Home />} />
<Route path={"/home/about"} element={<About />} /> */}
<Route path='*' element={<NotFound />} />
</Routes>
</BrowserRouter>
{/* <Home></Home>
<About></About> */}
</div>
)
}
}
export default App
import React from "react"
import { Outlet } from "react-router-dom"
class Layout extends React.PureComponent {
render() {
return (
<div id={'app'}>
layout
<Outlet />
</div>
)
}
}
export default Layout
import React from 'react'
import { Navigate } from 'react-router-dom'
class User extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
isLogin: false
}
}
render() {
let user = (
<div>
<h1>用户界面</h1>
<p>用户名: jonathan_lee</p>
<p>密码: www.it666.com</p>
</div>
)
let login = <Navigate to={'/login'} />
return this.state.isLogin ? user : login
}
}
export default User
嵌套路由
1.嵌套路由(子路由): 路由里面又有路由, 我们就称之为嵌套路由
import React from "react"
import { BrowserRouter, Routes, Link, Route } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
class App extends React.PureComponent {
render() {
return (
<div id={'app'}>
<BrowserRouter>
{/* <Link to={'/home'} relative='home'>Home</Link>
<Link to={'/home/about'} relative='/home/about'>About</Link> */}
<nav id="sidebar">
<NavLink to={'/home'}>Home</NavLink>
<NavLink end to={'/about'}>About</NavLink>
<NavLink end to={'/user'}>User</NavLink>
</nav>
{/* <Link to={'/home'}>Home</Link>
<Link to={'/home/about'}>About</Link> */}
<Routes>
<Route path="/" element={<Layout />}>
<Route index path='/home/*' element={<Home />} />
<Route end path="/about" element={<About />} />
</Route>
{/* <Route path='/home/*' element={<Home />} />
<Route end path="/about" element={<About />} /> */}
<Route path='user' element={<User />} />
<Route path="login" element={<Login />} />
{/* <Route path={'/home'} element={<Home />} />
<Route path={"/home/about"} element={<About />} /> */}
<Route path='*' element={<NotFound />} />
</Routes>
</BrowserRouter>
{/* <Home></Home>
<About></About> */}
</div>
)
}
}
export default App
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import NotFound from './NotFound'
function Hot() {
return (
<div>推荐</div>
)
}
function TopList() {
return (
<div>排行榜</div>
)
}
function PlayList() {
return (
<div>歌单</div>
)
}
class Home extends React.PureComponent {
render() {
return (
<div id={'app'}>
Home
<nav id="sidebar">
<NavLink end to={'/home'}>recommand</NavLink>
<NavLink end to={'/home/toplist'}>toplist</NavLink>
<NavLink end to={'/home/playlist'}>playlist</NavLink>
</nav>
<Routes>
<Route path='/' element={<Hot />} />
<Route path="/toplist" element={<TopList />} />
<Route path='/playlist' element={<PlayList />} />
<Route path='/*' element={<NotFound />} />
</Routes>
</div>
)
}
}
export default Home
手动路由跳转
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
function Hot() {
return (
<div>推荐</div>
)
}
function TopList() {
return (
<div>排行榜</div>
)
}
function PlayList() {
return (
<div>歌单</div>
)
}
class HomeDOM extends React.PureComponent {
render() {
return (
<div id={'app'}>
Home
<nav id="sidebar">
<NavLink end to={'/home'}>recommand</NavLink>
<NavLink end to={'/home/toplist'}>toplist</NavLink>
<NavLink end to={'/home/playlist'}>playlist</NavLink>
<button onClick={() => { this.btnClick() }}>歌单</button>
</nav>
<Routes>
<Route path='/' element={<Hot />} />
<Route path="/toplist" element={<TopList />} />
<Route path='/playlist' element={<PlayList />} />
<Route path='/*' element={<NotFound />} />
</Routes>
</div>
)
}
btnClick() {
console.log('this.props', this.props)
this.props.to('/home/playlist')
// this.props.history.push('/home/playlist')
}
}
const Home = widthUseNavigate(HomeDOM)
export default Home
import { useNavigate } from 'react-router-dom'
// 高阶组件包装useNavigate()功能
// 原因:类组件中无法使用useNavigate(),会报错
// React Hook "useNavigate" cannot be called in a class component.
function widthUseNavigate(WrapCompontent) {
// 设置别名
WrapCompontent.displayName = `widthUseNavigate${getDisplayName(WrapCompontent)}`
// console.log('WrapCompontent.displayName', WrapCompontent.displayName)
return function NavigateCompont() {
const navigate = useNavigate()
// 给传入的组件新增一个to方法,传给原始组件的props,在原始组件中通过this.props.to(参数)使用
return <WrapCompontent to={navigate}></WrapCompontent>
}
}
// 别名
function getDisplayName(WrapCompontent) {
// console.log('WrapCompontent', WrapCompontent.displayname, WrapCompontent.name)
return WrapCompontent.displayname || WrapCompontent.name || 'Component'
}
export default widthUseNavigate
路由传参
<NavLink to={'/home?name=study&age=18'}>Home</NavLink>
<NavLink to={'/home'} state={obj}>Home</NavLink>
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import { useLocation, useParams, useMatches } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
import qs from 'querystring'
function Hot() {
return (
<div>推荐</div>
)
}
function TopList(props) {
let params = useParams() // 获取动态参数
console.log('params', params) // id
return (
<div>排行榜</div>
)
}
function PlayList() {
return (
<div>歌单</div>
)
}
function propsRouteWithRouter(PropsRoute) {
return (props) => {
// let match = useMatches()
// console.log('match', match)
let params = useParams()
const search = qs.parse(useLocation().search.slice(1)) // 获取get传参形式的数据
const state = useLocation().state // Link | NavLink 通过state传的参数
console.log('params', params, search, state)
params = Object.assign(params, search, state)
return <PropsRoute {...props} params={params} />
}
}
class HomeDOM extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
...this.props.params
}
}
render() {
console.log('this.props', this.props.params, this.state)
return (
<div id={'app'}>
<div>data: {this.props.params.name}</div>
Home
<nav id="sidebar">
<NavLink end to={'/home'}>recommand</NavLink>
<NavLink end to={'/home/toplist/123123'}>toplist</NavLink>
<NavLink end to={'/home/playlist'}>playlist</NavLink>
<button onClick={() => { this.btnClick() }}>歌单</button>
</nav>
<Routes>
<Route path='/' element={<Hot />} />
<Route path="/toplist/:id" element={<TopList />} />
<Route path='/playlist' element={<PlayList />} />
<Route path='/*' element={<NotFound />} />
</Routes>
</div>
)
}
btnClick() {
console.log('this.props', this.props)
this.props.to('/home/playlist')
// this.props.history.push('/home/playlist')
}
}
const Home = widthUseNavigate(propsRouteWithRouter(HomeDOM))
export default Home
路由统一管理
现在虽然我们能通过路由实现组件切换, 但是现在我们的路由都比较分散, 不利于我们管理和维护 所以React也考虑到了这个问题, 也给我们提供了统一管理路由的方案
import React from "react"
import { BrowserRouter, useRoutes, Routes, Link, Route, Outlet } from "react-router-dom"
import Home from "./component/view/Home"
import About from "./component/view/About"
import NotFound from './component/view/NotFound'
import Layout from './component/view/Layout'
import User from './component/view/User'
import Login from './component/view/Login'
import './App.css'
import { NavLink } from "react-router-dom"
import DefineRoutes from './router/index'
class App extends React.PureComponent {
render() {
let obj = {
name: 'sss',
age: 16,
gender: 'man'
}
return (
<div id={'app'}>
<BrowserRouter>
{/* <Link to={'/home'} relative='home'>Home</Link>
<Link to={'/home/about'} relative='/home/abo ut'>About</Link> */}
<nav id="sidebar">
{/* <NavLink to={'/home?name=study&age=18'}>Home</NavLink> */}
<NavLink to={'/home'} state={obj}>Home</NavLink>
<NavLink end to={'/about'}>About</NavLink>
<NavLink end to={'/user'}>User</NavLink>
</nav>
{/* <Link to={'/home'}>Home</Link>
<Link to={'/home/about'}>About</Link> */}
{/* <Routes>
<Route path="/" element={<Layout />}>
<Route index path='/home/*' Component={Home} />
<Route end path="/about" element={<About />} />
</Route>
<Route path='user' element={<User />} />
<Route path="login" element={<Login />} />
<Route path='*' element={<NotFound />} />
</Routes> */}
<DefineRoutes></DefineRoutes>
</BrowserRouter>
{/* <Home></Home>
<About></About> */}
</div>
)
}
}
export default App
import React from "react"
import { NavLink, Routes, Route } from "react-router-dom"
import { useLocation, useParams, useMatches, Outlet } from "react-router-dom"
import widthUseNavigate from "./widthUseNavigate"
import NotFound from './NotFound'
// import DefineRoutes from '../../router/index'
import qs from 'querystring'
export function Hot() {
return (
<div>推荐</div>
)
}
export function TopList(props) {
let params = useParams()
console.log('params', params) // id
return (
<div>排行榜</div>
)
}
export function PlayList() {
return (
<div>歌单</div>
)
}
function propsRouteWithRouter(PropsRoute) {
return (props) => {
// let match = useMatches()
// console.log('match', match)
let params = useParams()
const search = qs.parse(useLocation().search.slice(1))
const state = useLocation().state
console.log('params', params, search, state)
params = Object.assign(params, search, state)
return <PropsRoute {...props} params={params} />
}
}
class HomeDOM extends React.PureComponent {
constructor (props) {
super(props)
this.state = {
...this.props.params
}
}
render() {
console.log('this.props', this.props.params, this.state)
return (
<div id={'app'}>
<div>data: {this.props.params.name} {this.state.age}</div>
Home
<nav id="sidebar">
<NavLink end to={'/home'}>recommand</NavLink>
<NavLink end to={'/home/toplist/123123'}>toplist</NavLink>
<NavLink end to={'/home/playlist'}>playlist</NavLink>
<button onClick={() => { this.btnClick() }}>歌单</button>
</nav>
{/* <Routes>
<Route path='/' element={<Hot />} />
<Route path="/toplist/:id" element={<TopList />} />
<Route path='/playlist' element={<PlayList />} />
<Route path='/*' element={<NotFound />} />
</Routes> */}
<Outlet />
</div>
)
}
btnClick() {
console.log('this.props', this.props)
this.props.to('/home/playlist')
// this.props.history.push('/home/playlist')
}
}
const Home = widthUseNavigate(propsRouteWithRouter(HomeDOM))
export default Home
import { memo } from 'react'
import Home from "../component/view/Home"
import About from "../component/view/About"
import NotFound from '../component/view/NotFound'
import Layout from '../component/view/Layout'
import User from '../component/view/User'
import Login from '../component/view/Login'
import { Hot, TopList, PlayList } from '../component/view/Home'
import { useRoutes } from "react-router-dom"
const DefineRoutes = memo(() => {
const routers = useRoutes(
[
{
path: '/',
element: <Layout />,
children: [
{
path: 'home',
element: <Home />,
children: [
{
path: '/home',
element: <Hot />,
},
{
path: 'toplist/:id',
element: <TopList />,
},
{
path: 'playlist',
element: <PlayList />,
}
]
},
{
path: 'about',
element: <About />
},
]
},
{
path: '/user',
element: <User />
},
{
path: '/login',
element: <Login />
},
{
path: '*',
element: <NotFound />
},
]
)
return routers
})
export default DefineRoutes
部分知识点学习