总述:因为在2021年11月推出了react-router-dom@6的版本,包括现在使用react脚手架创建项
目时, react-router-dom默认是6的版本, 以下将具体说明两个版本之间的不同的使用功能
如若需要了解react-router-dom@5版本相关的写法,可参考个人博客前期的文章,希望对你有所帮
助
概述
1、react-router以三个不同的包发布到npm上,他们分别为
1)react-router:路由的核心库,提供了很多的组件,钩子
2)react-router-dom:包含react-router所有内容,并添加了一些专门用于DOM的组件,例如
<BrowserRouter>等
3)react-router-native:包含react-router所有内容,并添加一些专门用于ReactNative的API,
例如<NativeRouter>等
2、与React Router5版本相比,改变了什么?
1)内置组件的变化:移除了<Switch/>,新增<Routes/>等
2)语法的变化:component={About}变为element={<About/>}等
3)新增了多个hook:useParams, useNavigate, useMatch等
4)官方明确推荐函数式组件了
Component内置组件
<BrowserRouter/>
作用:用于包裹整个应用
代码示例:
import React from 'react'
import { createRoot } from 'react-dom/client';//更新后的写法
import { BrowserRouter } from 'react-router-dom';
// react17版本写法
// import ReactDOM from 'react-dom'
import App from './App.jsx'
// react17版本写法
// ReactDOM.render(<App/>, document.getElementById('root'))
// react18版本写法
createRoot(document.getElementById('root')).render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
<HashRouter/>
说明:作用与BrowserRouter一样,但HashRouter修改的是地址的hash值
备注:6.X版本中HashRouter、BrowserRouter的用法与5.x相同
<Routes/>与<Route/>
1)6.x版本中移除了先前的Swith,引入了新的替代者Routes
2)Routes和route要配合使用,且必须要用Routes包裹Route
3)Route相当于一个if语句,如果其路径与当前URL匹配,则呈现其对应的组件
4)Route的caseSensitive属性用于指定:匹配时是否区分大小写(默认为false)
5)当URL发生变化时,Routes都会查看所有子Route元素以找打最佳匹配并呈现组件
6)Route也可以嵌套使用,且可配合useRoutes()配置路由表,但需要通过Outlet组件来渲染其子
组件
<Link/>
作用:修改URL,且不发送网络请求(路由链接)
注意:外侧需要用BrowserRouter或HashRouter包裹
示例代码:
import React from 'react'
import { Link } from 'react-router-dom'
export default function Test() {
return (
<div>
<Link to='/路径'>按钮</Link>
</div>
)
}
<NavLink/>
作用:与Link组件类似,且可实现导航的高亮效果<
import { NavLink } from "react-router-dom";
// 注意:NavLink默认类名是active,下面是自定义的class
<NavLink
to='login'
className={({isActive}) => {
console.log('home', isActve);
return isActive ? 'base one' : 'base'
}}
>login</NavLink>
// 默认情况下,当Home的子组件匹配成功后,Home的导航也会亮
// 当NavLink添加end属性后,若Home的子组件匹配成功,则Home的导航没有高亮效果
{/* <NavLink to='home' end></NavLink> */}
<Navigate/>
作用:只要Navigate组件被渲染,就会修改路径,切换视图
replace属性用于控制跳转模式(push或者是replace,模式是push)
示例代码:
import React, {useState} from 'react'
import { Navigate } from 'react-router-dom';
export default function Home() {
const [sum, setSum] = useState(1)
console.log(useState(1));
return (
<div>
<h3>我是Home组件</h3>
{sum === 2 ? <Navigate to='/about'/> : <h4>当前sum的值是:{sum}</h4>}
<button onClick={() => setSum(2)}>点我将sum变为2</button>
</div>
)
}
<Outlet/>
当Route产生嵌套时,渲染其对应的后续子路由
示例:
import About from "../pages/About"
import Home from "../pages/Home"
import News from "../pages/News"
import Message from "../pages/Message"
import { Navigate } from "react-router-dom"
export default [
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>,
children:[
{
path:'news',
element:<News/>
},
{
path:'message',
element:<Message/>
}
]
},
{
path:'/',
element:<Navigate to='/about'/>
}
]
// Home.jsx
import React from 'react'
import { NavLink, Outlet } from 'react-router-dom'
export default function Home() {
return (
<div>
<h3>我是Home组件</h3>
<div>
<ul className='nav nav-item'>
<li>
{/* to的写法一,在父级路径下在写子级路径 */}
{/* <NavLink className='list-group-item' to="/home/news">News</NavLink> */}
{/* to的写法二 */}
<NavLink className='list-group-item' to="news">News</NavLink>
</li>
<li>
<NavLink className='list-group-item' to="/home/message">Message</NavLink>
</li>
</ul>
{/* 指定路由组件呈现的位置 */}
<Outlet/>
</div>
</div>
)
}
Hooks
useRoutes()
作用:根据路由表,动态创建Routes和Route
示例代码:
routes-index.js
import About from "../pages/About"
import Home from "../pages/Home"
import { Navigate } from "react-router-dom"
export default [
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>
},
{
path:'/',
element:<Navigate to='/about'/>
}
]
App.jsx
import React from 'react'
import {NavLink, useRoutes} from 'react-router-dom'
import routes from './routes/index'
export default function App() {
// 根据路由表生成对应的路由规则
const element = useRoutes(routes)
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>Vue Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
{/* 在React中靠路由链接切换组件 */}
<NavLink className="list-group-item" to="/about">About</NavLink>
<NavLink className="list-group-item" to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* 注册路由 */}
{/* <Routes>
<Route path= "/about" element={<About/>}/>
<Route path="/home" element={<Home/>}/>
<Route path='/' element={<Navigate to='/about'/>}/>
</Routes> */}
{element}
</div>
</div>
</div>
</div>
</div>
)
}
useNavigate()
作用:返回一个函数用来实现编程式导航
示例代码:
Message.jsx
import React, {useState} from 'react'
import { Link, Outlet, useNavigate } from 'react-router-dom'
export default function Message() {
const [message] = useState([
{id:'001', title:'消息001', content:'锄禾日当午'},
{id:'002', title:'消息002', content:'汗滴禾下土'},
{id:'003', title:'消息003', content:'谁知盘中餐'},
{id:'004', title:'消息004', content:'粒粒皆辛苦'}
])
const navigate = useNavigate()
function showDeatil(m) {
navigate('detail', {
replace:false,
state:{
id:m.id,
title:m.title,
content:m.content
}
})
}
return (
<div>
<ul>
{
message.map((m) => {
return <li key={m.id}>
<Link to='detail'
state={{
id:m.id,
title:m.title,
content:m.content
}}
>{m.title}</Link>
<button onClick={() =>showDeatil(m)}>查看详情</button>
</li>
})
}
</ul>
<hr/>
<Outlet/>
</div>
)
}
Header.jsx
import React from 'react'
import { useNavigate } from 'react-router-dom'
export default function Header() {
const navigate = useNavigate()
function forward() {
navigate(1)
}
function back() {
navigate(-1)
}
return (
<div>
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>Vue Router Demo</h2></div>
</div>
<button onClick={forward}>前进</button>
<button onClick={back}>后退</button>
</div>
)
}
useParams()
作用:当前匹配路由的params参数,类似5中的match.param
代码示例:
Message.jsx
import React, {useState} from 'react'
import { Link, Outlet } from 'react-router-dom'
export default function Message() {
const [message] = useState([
{id:'001', title:'消息001', content:'锄禾日当午'},
{id:'002', title:'消息002', content:'汗滴禾下土'},
{id:'003', title:'消息003', content:'谁知盘中餐'},
{id:'004', title:'消息004', content:'粒粒皆辛苦'}
])
return (
<div>
<ul>
{
message.map((m) => {
return <li key={m.id}>
<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link>
</li>
})
}
</ul>
<hr/>
<Outlet/>
</div>
)
}
routes-index,js
import About from "../pages/About"
import Home from "../pages/Home"
import News from "../pages/News"
import Message from "../pages/Message"
import Detail from "../pages/Detail"
import { Navigate } from "react-router-dom"
export default [
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>,
children:[
{
path:'news',
element:<News/>
},
{
path:'message',
element:<Message/>,
children:[
{
path:'detail/:id/:title/:content',
element:<Detail/>
}
]
}
]
},
{
path:'/',
element:<Navigate to='/about'/>
}
]
Detail.jsx
import React from 'react'
import { useParams, useMatch } from 'react-router-dom'
export default function Detail() {
// 读取params参数的第一种写法
const {id, title, content} = useParams()
// 读取params参数的第二种写法
const a = useMatch('/home/message/detail/:id/:title/:content')
console.log(a);
return (
<div>
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
</div>
)
}
useSearchParams()
作用:用于读取和修改当前位置的URL中的查询字符串
返回:返回一个包含两个值得数组,内容分别为当前的search参数,更新search的函数
示例代码:
Message.jsx
import React, {useState} from 'react'
import { Link, Outlet } from 'react-router-dom'
export default function Message() {
const [message] = useState([
{id:'001', title:'消息001', content:'锄禾日当午'},
{id:'002', title:'消息002', content:'汗滴禾下土'},
{id:'003', title:'消息003', content:'谁知盘中餐'},
{id:'004', title:'消息004', content:'粒粒皆辛苦'}
])
return (
<div>
<ul>
{
message.map((m) => {
return <li key={m.id}>
<Link to={`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>
</li>
})
}
</ul>
<hr/>
<Outlet/>
</div>
)
}
Detail.jsx
import React from 'react'
import { useSearchParams, useLocation } from 'react-router-dom'
export default function Detail() {
// 获取search参数的第一种
const [search, setSearch] = useSearchParams()
const id = search.get('id')
const title = search.get('title')
const content = search.get('content')
// 获取searh参数的第二种写法
const a = useLocation()
console.log(a);
return (
<div>
<ul>
<li>
<button onClick={() => {setSearch('id=008&title=哈哈&content=嘻嘻')}}>更新收到的参数</button>
</li>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
</div>
)
}
useLocation()
作用:获取当前location信息,对应5中的路由组件的location属性
示例代码:
Message.jsx
import React, {useState} from 'react'
import { Link, Outlet } from 'react-router-dom'
export default function Message() {
const [message] = useState([
{id:'001', title:'消息001', content:'锄禾日当午'},
{id:'002', title:'消息002', content:'汗滴禾下土'},
{id:'003', title:'消息003', content:'谁知盘中餐'},
{id:'004', title:'消息004', content:'粒粒皆辛苦'}
])
return (
<div>
<ul>
{
message.map((m) => {
return <li key={m.id}>
<Link to='detail'
state={{
id:m.id,
title:m.title,
content:m.content
}}
>{m.title}</Link>
</li>
})
}
</ul>
<hr/>
<Outlet/>
</div>
)
}
Detail.jsx
import React from 'react'
import { useLocation } from 'react-router-dom'
export default function Detail() {
const {state:{id, title, content}} = useLocation()
return (
<div>
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
</div>
)
}
useMatch()
作用:用于获取paramas参数
代码示例
import React from 'react'
import { useParams, useMatch } from 'react-router-dom'
export default function Detail() {
// 读取params参数的第一种写法
const {id, title, content} = useParams()
// 读取params参数的第二种写法
const a = useMatch('/home/message/detail/:id/:title/:content')
console.log(a);
return (
<div>
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
</div>
)
}
useInRouterContext()
作用:如果组件在Router的上下文中呈现,则useInRouterContext钩子返回true,否则返回false
useNavigationType()
作用:返回当前的导航类型(用户是如何来到当前页面的)
返回值有pop, push, replace
备注:pop是指在浏览器中直接打开了这个路由组件(刷新页面)
代码示例
import React from 'react'
import { useNavigationType } from 'react-router-dom'
export default function News() {
console.log(useNavigationType());
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
)
}
useOutlet()
作用:用来呈现当前组件中要渲染的嵌套路由
import React from 'react'
import { NavLink, Outlet, useOutlet} from 'react-router-dom'
export default function Home() {
console.log('#########',useOutlet());
return (
<div>
<h3>我是Home组件</h3>
<div>
<ul className='nav nav-item'>
<li>
{/* to的写法一,在父级路径下在写子级路径 */}
{/* <NavLink className='list-group-item' to="/home/news">News</NavLink> */}
{/* to的写法二 */}
<NavLink className='list-group-item' to="news">News</NavLink>
</li>
<li>
<NavLink className='list-group-item' to="/home/message">Message</NavLink>
</li>
</ul>
{/* 指定路由组件呈现的位置 */}
<Outlet/>
</div>
</div>
)
}
useResolvedPath()
作用:给定一个URL值,解析其中的path、search、hash值
import React from 'react'
import { useNavigationType, useResolvedPath } from 'react-router-dom'
export default function News() {
console.log(useNavigationType());
console.log(useResolvedPath('/user?id=001&title=哈哈'));
return (
<div>
<ul>
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
)
}