1 概念
从版本的React-Router5.x开始,路由彻底改变了,和以后的版本完全不兼容。所以出去开发时注意版本。
对当页面应用模式提供多页面效果
Link和useNavigate实现组件切换时,实计上伴随着组件的销毁与创建,所以建议只有整体页面切换时才使用路由,而局部切换时使用最原始的隐藏显示为佳,这样可以保让组件中通过ajax得到的数据一直存在。同样的道理,子路由的使用也需要特别小心
2 环境
(1)下载第三方模块
(a)ts开发情况下, 下载模块"react-router-dom"和 “@types/react-router-dom”
npm i --save react-router-dom @types/react-router-dom
(b)js开发情况下, 只需下载模块"react-router-dom"
(2)引入
import {
BrowserRouter as Router, //BrowserRouter太长,常常使用别名Router
Route,
Routes,
Link,
useNavigate,
useParams,
useLocation,
Navigate
} from 'react-router-dom';
BrowserRouter太长,常常使用别名Router
3 创建路由
<BrowserRouter>
<Routes>
<Route path='/main' element={<Main />} />
<Route path='/one' element={<One />} />
<Route path='/two' element={<Two />} />
</Routes>
</BrowserRouter>
<BrowserRouter>
{/*Nav这个自定义组件与路由出来的界面同时显示, 页面跳转-Link和useNavigate可以在该组件中控制*/}
<Nav />
<Routes>
<Route path='/main' element={<Main />} />
<Route path='/one' element={<One />} />
<Route path='/two' element={<Two />} />
</Routes>
</BrowserRouter>
4 页面跳转-Link和useNavigate
Link和useNavigate 必须位于BrowserRouter标签内部
Link相当于超连接
useNavigate是hook
import {Link, useNavigate} from 'react-router-dom';
Line标签
<Link to={{pathname:'/one'}}>one</Link>
或ts代码-useNavigate
let navigate = useNavigate();
function toTwo() {
navigate({pathname:'/one'});
}
5 路由使用注意事项
Link和useNavigate实现组件切换时,实计上伴随着组件的销毁与创建,所以建议只有整体页面切换时才使用路由,而局部切换时使用最原始的隐藏显示为佳,这样可以保让组件中通过ajax得到的数据一直存在。同样的道理,子路由的使用也需要特别小心
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sQRHqemV-1666064597950)(static/image-20220215154045634.png)]
6 传参数
1 state传参数
传参数只能使用hook-useNavigate函数
//传递参数关键代码
import {useNavigate} from 'react-router-dom';
let navigate = useNavigate();
navigate({pathname:'/one'},{state:{id:1,sex:'女',name:'小五'}});
接收参数使用hook-useLocation函数,接收到的对象state是一个Object类型,所以必须类型断言才能取出属性值
//接收参数关键代码
import {useLocation} from 'react-router-dom';
const location = useLocation();
let stu = location.state as {id:number,sex:string,name:string};
2 动态传参数
第一步设置可传参数,第二步传参数,第三步使用hook-useParams函数接收参数
设置可传参数
<Route path='/two/:name/:sex' element={<Two />} />
传参
navigate({pathname:`/two/小王/女`});
或
<Link to={{pathname:`/two/小王/女`}}>two</Link>
接收参数
import {Link, useParams} from 'react-router-dom';
let person = useParams();
console.log(person.name,person.sex)
3 通过url传参数
传参
{pathname:'/one?name=泪王'}
接收
import {useLocation} from 'react-router-dom';
let location = useLocation();
let search = location.search;
search = decodeURI(search);//转码
console.log(search);// /one?name=泪王
7 配置符
<Route path="/*" element={<组件1 />}></Route>
<Route path="/test" element={<组件2 />}></Route>
{/*
/test匹配到组件2
/teacher匹配到组件1
*/}
8 子路由
1 子路由配置
第1步 在配置主路由的path属性后面加"/*"
//Ziluyou.tsx
<BrowserRouter>
<Routes>
<Route path="/" element={<Main />}></Route>
<Route path="/one/*" element={<One />}></Route>
<Route path="/two" element={<Two />}></Route>
<Route path="/three" element={<Three />}></Route>
</Routes>
</BrowserRouter>
第2步在主路由对应的组件中使用配置新的路由, 子路由的访问path为"主路由+子路由"
//One.tsx
<Routes>
<Route path="/" element={<Person />} />
<Route path="/stu" element={<Stu />} />
<Route path="/teacher" element={<Teacher />} />
<Route path="/boss" element={<Boss />} />
</Routes>
{/*
/---Main
/two---Two
/Three----Three
/one匹配到<Person />
/one/stu匹配到组件<Stu />
/one/teacher匹配到组件<Teacher />
/one/boss 匹配到组件<Boss />
/one/aabb 匹配不到组件
*/}
2 主路由与子路由相互跳转
- 不管是主路由还是子路由,都可以在浏览器中输入正确的地址访问到;
- 不管是主路由还是子路由,只要组件内嵌在标签"BrowserRouter"中,就可以使用hook-useNavigate或标签Link直接使用正确的路由path访问到;
9 重定向
1 重定向基础
重定向需使用到组件Navigate
import {Navigate} from 'react-router-dom';
Route中的element不设置组件,而设置别的已经设置好的Route的path, 显示效果就是该path对应的组件。
子路由可以重定向到主路由,主路由中也可以重定向到子路由。
<Routes>
<Route path="/" element={<Main />}></Route>
<Route path="/one/*" element={<One />}></Route>
<Route path="/two" element={<Two />}></Route>
<Route path="/three" element={<Three />}></Route>
<Route path="/*" element={<Page404 />}></Route>
{/* 主路由重定向到主路由: 重定向到path:/two对应的组件<Two />中, 网址会显示为/two */}
<Route path="/b" element={<Navigate to="/two" />} />
{/* 主路由重定向到子路由: 定向到path:/one/stu对应的组件XXX中,网址会显示为/one/stu */}
<Route path="/a" element={<Navigate to="/one/stu" />} />
</Routes>
重定向还有一种方式, 在组件的返回值中使用
import React from 'react';
import {Navigate} from 'react-router-dom';
export default function Index(flag:string) {
if(flag=="stu") {
return <Navigate to="/one" replace={true} />
}else {
return <Navigate to="/two" replace={true} />
}
}
2 路径错误默认显示页面
主路由中使用/*来匹配,子路由中重定向到主路由中的/*
//App.tsx 第一级路由(主路由)
<Route path="/" element={<Main />}></Route>
<Route path="/one/*" element={<One />}></Route>
<Route path="/two" element={<Two />}></Route>
<Route path="/three" element={<Three />}></Route>
<Route path="/*" element={<Page404 />}></Route>
{/*
<Page404 />是路由错误的默认访问网页
localhost:3000--<Main>
localhost:3000/one--<One>
localhost:3000/two--<Two>
localhost:3000/three---<Three>
localhost:3000/aabb---<Page404>
*/}
//One.tsx 第二级路由(子路由)
<Routes>
<Route path="/boss" element={<Boss />} />
<Route path="/*" element={<Navigate to="/404" />} />
</Routes>
{/*
localhost:3000/one/boss--<Boss>
localhost:3000/one/aabb--重定向到localhost:3000/404--匹配主路由的/*---找到<Page404 />
<Navigate to="/404" />中的"/404"是任意写的一个不存在的路由path,所以不是非要写成"/404"
*/}
10 路由首守-登陆判断
写一个带插槽的组件,在该组件中统一判断是否登陆,进而决定该组件中插入的组件是否正常加入。
在路由配置组件时,所有组件使用插槽组件包裹。
import React,{useState} from 'react';
import {BrowserRouter,Link, Routes, Route, Navigate} from 'react-router-dom';
import Main from './Main';
import Login from './Login';
import Goods from './Goods';
import About from './About';
import RouterFilter from './ProtectedRouter/RouterFilter';
function Index() {
const[islogin, setIslogin] = useState<boolean>(false);
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<RouterFilter><Main /></RouterFilter>}></Route>
<Route path="/goods" element={<RouterFilter><Goods /></RouterFilter>}></Route>
<Route path="/about" element={<RouterFilter><About /></RouterFilter>}></Route>
<Route path="/login" element={<Login />}></Route>
</Routes>
</BrowserRouter>
);
}
export default Index;
import React,{useContext} from 'react'
import MyContext from './MyContext';
import {Navigate} from 'react-router-dom';
function RouterFilter({children}:any) {
if(已经登陆) {
return children;
}else {//未登陆
return <Navigate to="/login" replace={true} />
}
}
export default RouterFilter;
|