npm install react-router-dom@6 -S
路由链接(携带参数)
<Link className="nav" to={`/b/child2?age=20&name=zhangsan`}>Child2</Link>
或
<Link to={`/b/child1/${id}/${title}`}>Child1</Link>
注册路由(声明接受)
<Route path="/b/child1/:id/:title" component={Test} />
接收参数
import { useParams } from "react-router-dom";
const params = useParams();
路由链接(携带参数)
<Link className="nav" to={`/b/child2?age=20&name=zhangsan`}>Child2</Link>
注册路由(无需声明,正常注册即可)
<Route path="/b/child2" component={Test}/>
接收参数:
接收参数方法1:
import { useLocation } from "react-router-dom";
import qs from "query-string";
const { search } = useLocation();
search参数 => {age: "20", name: "zhangsan"}
接收参数方法2:
import { useSearchParams } from "react-router-dom";
const [searchParams, setSearchParams] = useSearchParams();
console.log( searchParams.get("id")); // 12
备注:获取到的search是urlencoded编码字符串(例如: ?age=20&name=zhangsan),需要借
助query-string解析参数成对象
通过Link的state属性传递参数
<Link
className="nav"
to={`/b/child2`}
state={{ id: 999, name: "i love merlin" }}
>
Child2
</Link>
注册路由(无需声明,正常注册即可)
<Route path="/b/child2" component={Test}/>
接收参数:
import { useLocation } from "react-router-dom";
const { state } = useLocation();
state参数 => {id: 999, name: "我是梅琳"}
备注:刷新也可以保留住参数
navigate(/invoices/${number}, { state: 1 })
<NavLink to={/invoices/${number}} state={{a:1}}>
let location = useLocation()
let data=location.state
let params = useParams()
let data=params.get('参数名')
HashRouter:在路径中包含了#,相当于HTML的锚点定位。(# 符号的英文叫hash,所
以叫HashRouter)
BrowserRouter:使用的是HTML5的新特性History,没有HashRouter(锚点定位)那样通
用,低版本浏览器可能不支持。
BrowserRouter:进行组件跳转时可以传递任意参数实现组件间的通信
HashRouter:不能(除非手动拼接URL字符串),因此一般配合Redux使用,实现组件间的
数据通信。
HashRouter
HashRouter相当于锚点定位,因此不论#后面的路径怎么变化,请求的都相当于是#之前的那个页面。可以很容易的进行前后端不分离的部署(也就是把前端打包后的文件放到服务器端的public或static里),因为请求的链接都是ip地址:端口/#/xxxx,因此请求的资源路径永远为/,相当index.html,而其他的后端API接口都可以正常请求,不会和/冲突,由于前后端不分离也不会产生跨域问题。缺点就是丑,路径里总有个#
BrowserRouter
因为BrowserRouter模式下请求的链接都是ip地址:端口/xxxx/xxxx,因此相当于每个URL都会访问一个不同的后端地址,如果后端没有覆盖到路由就会产生404错误。
可以通过加入中间件解决,放在服务器端路由匹配的最后,如果前面的API接口都不匹配,则返回index.html页面。但这样也有一些小问题,因为要求前端路由和后端路由的URL不能重复。
比如商品列表组件叫/product/list,而请求商品列表的API也是/product/list,那么就会访问不到页面,而是被API接口匹配到
解决方法:
进行前后端分离的部署,比如前端地址ip1:端口1,后端接口地址ip2:端口2,使用Nginx反向代理服务器进行请求分发。前端向后端发起请求的URL为nginx所在的服务器+/api/xxx,通过NGINX的配置文件判断,如果URL以api开头则转发至后端接口,否则转发至前端的地址,访问项目只需访问Nginx服务器即可。
在routes路由配置文件添加一个重定向路由
{
path: '/redirect',
auth:false,
component: lazy(() => import('../page/Redirect/Redirect')),
}
编写重定向组件,在组件内部实现路由的跳转,从而实现路由的重定向
import { useNavigate } from "react-router-dom";
import { useEffect } from "react";
const Redirect=(props:any)=> {
let navigate = useNavigate();
useEffect(() => {
navigate("/Portal/Home");
});
return <></>;
}
export default Redirect
<Routers>:一组路由(代替原有的<Switch>,所有的子路由都用基础的Router Children表· 示)
<Route>: 基础路由(Route是可以嵌套的,解决原有V5中严格模式)
<Link>: 导航组件(在实际页面中跳转使用)
<Outlet/>: 自适应渲染组件(根据实际路由url自动选择组件,一般用来实现嵌套路由)
useParams: 返回当前参数(根据路径读取参数)
useNavigate: 返回当前路由(代替原有V5中的useHistory,一般用来跳转页面)
useOutlet:返回根据路由生成的element(用来呈现当前组件中要渲染的嵌套路由)
useLocation: 返回当前的location对象 (可以获取useNavigate('',{state:{id}}))里面的id
参数。
useRoutes:同Routers组件相同,只不过是在js中使用(可用做配置路由)
useSearchParams:用来匹配URL中?后面的参数(用来获取 ?x=1&y=100 这样的参数)
react-router 提供了路由核心api。如Router, Route, Switch等,但没有提供有关dom操作进行路由跳转的api
react-router-dom在react-router的基础上扩展了可操作dom的api。Link组件,会渲染成一个 a 标签;BrowserRouter和hashRouter组件,前者使用pushState和popState事件构建路由,后者使用 hash 和 hashchange 事件构建路由。 react-router-dom 中依赖了 react-router,所以安装的时候只要安装 react-router-dom.