react-router-dom6的变化
-
将 Switch 升级为 Routes
-
路由匹配组件参数 由 component 改为 element
-
相对路径识别(子路由不需要补全父路由的path,react会自动补全)
-
用 useNavigate 替代 useHistory
-
废弃 Redirect 标签,使用 Navigate 标签实现路由重定向
-
优化路由嵌套,添加 outlet 标签(路由出口,路由组件的显示。相当于vue-router里的<router-view>)
-
使用 index 标识默认路由
-
添加 useResolvedPath hooks
-
添加 useSearchParams 读取和设置url参数
-
link 标签跳转的path 将支持 . 和 .. 这种语法(类比于 terminal 中的 cd .. 返回上级菜单 )
-
path 通配符将只支持 * 和 :(以前的?等将不再支持)
-
添加 useOutletContext 用于 路由之间共享状态
一、嵌套的路由配置
一级路由创建
1.新建views文件夹 容纳路由页面 新建router文件夹容纳路由配置
./src/router/index.ts
import React from 'react'
// 1.引用路由配置
import {Route} from "react-router-dom"
// 2.引用路由页面
import Home from "../views/Home.jsx"
import Phone from "../views/Phone.jsx"
import Shop from "../views/Shop.jsx"
export default function index() {
return (
<>
{/* 3.设置路由规则 */}
<Route path="/home" element={<Home/>}></Route>
<Route path="/phone" element={<Phone/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
</>
)
}
2.设置路由配置放到到入口文件中
./src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
// 1.引用路由配置文件
import App from './router';
import {BrowserRouter} from "react-router-dom"
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
3.运行之后发现如下错误
Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
错误是说Route组件不能直接渲染 必须用一个Routes组件进行包裹使用 注意在V6版本中 Routes就是V5版本的Switch组件
对
./src/router/index.ts进行修改,用<Routes>标签包裹<Route>
import React from 'react'
// 引用Routes
import {Route,Routes} from "react-router-dom"
import Home from "../views/Home.jsx"
import Phone from "../views/Phone.jsx"
import Shop from "../views/Shop.jsx"
export default function index() {
return (
<>
{/* 使用唯一渲染 */}
<Routes>
<Route path="/home" element={<Home/>}></Route>
<Route path="/phone" element={<Phone/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
</Routes>
</>
)
}
路由重定向
Navigate
import React from 'react'
import {Route,Routes,Navigate} from "react-router-dom"
import Home from "../views/Home.jsx"
import Phone from "../views/Phone.jsx"
import Shop from "../views/Shop.jsx"
export default function index() {
return (
<>
<Routes>
<Route path="/home" element={<Home/>}></Route>
<Route path="/phone" element={<Phone/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
{/* 设置路由重定向 */}
<Route path="/" element={<Navigate to="/home"/>}></Route>
</Routes>
</>
)
}
404页面
import React from 'react'
import {Route,Routes,Navigate} from "react-router-dom"
import Home from "../views/Home.jsx"
import Phone from "../views/Phone.jsx"
import Shop from "../views/Shop.jsx"
import No from "../views/No.jsx"
export default function index() {
return (
<>
<Routes>
<Route path="/home" element={<Home/>}></Route>
<Route path="/phone" element={<Phone/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
<Route path="/" element={<Navigate to="/home"/>}></Route>
{/* 404 */}
<Route path="*" element={<No/>}></Route>
</Routes>
</>
)
}
二级路由
1.新建二级路由页面 与规则的配置
./src/router/index.ts
import React from 'react'
import {Route,Routes,Navigate} from "react-router-dom"
import Home from "../views/Home.jsx"
import Phone from "../views/Phone.jsx"
import Shop from "../views/Shop.jsx"
import No from "../views/No.jsx"
import Era from "../views/er/Era.jsx"
import Erc from "../views/er/Erc.jsx"
export default function index() {
return (
<>
<Routes>
<Route path="/home" element={<Home/>}>
{/* 在一级路由规则中直接嵌套 */}
{/*
<Route path="/home/era" element={<Era/>}></Route>
<Route path="/home/erc" element={<Erc/>}></Route>
*/}
{/* 也可以直接使用下面的相对路径写法 两个写法是相同的 */}
<Route path="era" element={<Era/>}></Route>
<Route path="erc" element={<Erc/>}></Route>
</Route>
<Route path="/phone" element={<Phone/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
<Route path="/" element={<Navigate to="/home"/>}></Route>
<Route path="*" element={<No/>}></Route>
</Routes>
</>
)
}
2.设置路由出口 Outlet
./src/app.tsx
import React from 'react'
import {Outlet} from "react-router-dom"
export default function Home() {
return (
<div>
home
<Outlet></Outlet>
</div>
)
}
路由导航
声明式
Link与NavLink方式进行跳转
<Link to="/home">home</Link>
<Link to="/phone">phone</Link>
<Link to="/shop">shop</Link>
或者
<NavLink to="/home">home</NavLink>
<NavLink to="/phone">phone</NavLink>
<NavLink to="/shop">shop</NavLink>
修改NavLink默认类名--》NavLink默认选中类名为active 如果想修改 还是使用className来修改里面传入回调函数
import React from 'react'
import {NavLink} from "react-router-dom"
export default function Demolink() {
return (
<div>
<NavLink to="/home" className={({isActive})=>isActive?'xiaoming':''}>home</NavLink>
<NavLink to="/phone" className={({isActive})=>isActive?'xiaoming':''}>phone</NavLink>
<NavLink to="/shop" className={({isActive})=>isActive?'xiaoming':''}>shop</NavLink>
</div>
)
}
编程式
使用 useNavigate()来完成
import React from 'react'
// 1.引用
import {useNavigate} from "react-router-dom"
export default function Demolink() {
// 2.调用
let navigate=useNavigate()
let fun=()=>{
// 3.使用
navigate("/home")
}
return (
<div>
<button onClick={fun}>点我去home</button>
</div>
)
}
路由传参
params方式
1.配置接受参数
<Route path="/phone/:id" element={<Phone/>}></Route>
2.传参
import React from 'react'
import { useNavigate } from "react-router-dom";
export default function Shop() {
let navigate = useNavigate();
let fun=()=>{
// 编程式
navigate('/phone/我是参数')
}
return (
<div>
shop
<button onClick={fun}>点我使用params方式发送数据给phone</button>
//声明式
<Link to='/phone/我是参数'>点我使用params方式发送数据给phone</Link>
</div>
)
}
3.接参 用 useParams
import React from 'react'
import { useEffect } from 'react';
// 通过useParams接受路由传值
import { useParams } from "react-router-dom";
export default function Phone() {
const params = useParams();
// js接收
useEffect(()=>{
console.log(params.id)
},[])
return (
<div>
{/* 页面接收 */}
phone--{params.id}
</div>
)
}
特点
参数会在url后面拼接传递 localhost:xxxx/phone/我是参数 并且刷新不丢失
search方式
1.传参
import React from 'react'
import { useNavigate,Link} from "react-router-dom";
export default function Shop() {
let navigate = useNavigate();
let fun=()=>{
// 发送
navigate('/phone?id=999&key=val&key=val')
}
return (
<div>
shop
<button onClick={fun}>点我使用params方式发送数据给phone</button>
{/* 声明式发送方式 */}
<Link to={{ pathname:`/phone?id=999` }}>Child</Link>
</div>
)
}
2.接参
import React from 'react'
import { useEffect } from 'react';
// 通过useSearchParams接受路由传值
import { useSearchParams } from "react-router-dom";
export default function Phone() {
// 返回数组长度为2的数据 第一个为传递过来的数据 第二个是修改传递过来的数据
const [searchParams, setSearchParams] = useSearchParams();
// js接收
useEffect(()=>{
console.log(searchParams.get("id"))
},[])
return (
<div>
{/* 页面接收 */}
phone--{searchParams.get('id')}
</div>
)
}
修改接收的路由参数---在有的项目里面 点击随便看看类似的功能
import React from 'react'
import { useEffect } from 'react';
// 通过useSearchParams接受路由传值
import { useSearchParams } from "react-router-dom";
export default function Phone() {
// 返回数组长度为2的数据 第一个为传递过来的数据 第二个是修改传递过来的数据
const [searchParams, setSearchParams] = useSearchParams();
useEffect(()=>{
console.log(searchParams.get("id"))
},[])
return (
<div>
phone--{searchParams.get('id')}
{/* // 同时页面内也可以用第二个参数方法来改变路由 */}
<button onClick={()=>{setSearchParams({"id":2})}}>点我修改接收的路由参数</button>
</div>
)
}
特点
参数会在url后面拼接传递 localhost:xxxx/phone?id=2 并且刷新不丢失
state方式
传参:
<Link to="/Detail" state={{ id: "q01001" }}>state:01001</Link>
接参:
import React from 'react';
import {useLocation} from "react-router-dom";
export default function Detail() {
const location = useLocation();
console.log("location.state.id",location.state.id);
return (
<div>
<p>location.state.id:{location.state.id}</p>
</div>
)
}