react路由6版本与5版本的对比
好久没写react项目了,最近使用react路由时,闹了不少乌龙。简单说下吧,react路由6版本与5版本的写法还是有很大区别的。
router-router-dom6 就是在2021年11月发布的版本,我们称之为react路由6版本。个人感觉自从react hooks一出来之后,函数式组件写法越来越受欢迎,对应的类式组件写法正在被淡出大众视野。6版本就是在此环境下产生的。
一、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 用于 路由之间共享状态
看看,是不是感觉跟react路由5版本差异挺大的?
关于5版本的路由写法前面已经详细介绍过,有兴趣的道友请移步我前面的博客研究一下。本文只详细介绍6版本路由的用法。
二、react路由6的基本用法
安装
npm install --save react-router-dom@6.x
使用
react项目中,我们把index.js文件改一改:
1 // 从 react-dom/client 引入 ReactDOM 2 import ReactDOM from 'react-dom/client' 3 //引入BrowserRouter 4 import { BrowserRouter } from 'react-router-dom' 5 import App from './App' 6 ReactDOM.createRoot(document.getElementById('root')).render( 7 <BrowserRouter> 8 <App /> 9 </BrowserRouter> 10 )
上面的<BrowserRouter>就是history路由(浏览器地址栏不带#),除了<BrowserRouter>还有<HashRouter>。
BrowserRouter和HashRouter两者的区别如下:
1.底层原理不同:
BrowserRouter使用的是H5的history API
HashRouter使用的是URL的哈希值
2.path的表现形式不同
BrowserRouter的路径中没有#,例如localhost:3000/add
HashRouter的路径包含#,例如localhost:3000/#/add
3.刷新后对路由state参数的影响
BrowserRoute没有任何影响,因为state保存在history对象中
HashRouter刷新后导致路由state参数的丢失
创建路由的方式
1.路由的基本使用
import { NavLink, Routes, Route, Navigate } from 'react-router-dom' import About from './components/About.jsx' import Home from './components/home.jsx' import Children from "../components/children.jsx" export default function App() { return ( <div> <NavLink to="/home">Home</NavLink> <NavLink to="/about">About</NavLink> <Routes> <Route path="/home" element={<Home />}> {/*嵌套路由(子路由)*/} <Route path="/about" element={<About />}></Route> </Route> <Route path="/about" element={<About />}></Route> <Route path="/" element={<Navigate to="/home" />}></Route> </Routes> </div> ) }
<Navigate>
:只要 <Navigate>
组件被渲染,就会修改路径,切换视图。可用于路由重定向,设置进入页面默认跳转的路由页面。
2.创建路由表
// 路由表 // routes/index.js import { Navigate } from 'react-router-dom' import About from '../components/About.jsx' import Home from '../components/home.jsx' import Children from "../components/children.jsx" import const routes = [ //路由重定向 { path: '/', element: <Navigate to="/home" />, }, { path: '/home', element: <Home />, //创建子路由 children:[ { path:"children", element:<Children/> } ] }, { path: '/about', element: <About/>, }, ] export default routes
然后在 App.jsx中挂载路由:
//App.jsx import { NavLink,useRoutes} from 'react-router-dom' import About from './components/About.jsx' import Home from './components/home.jsx' //引入路由表 import routes from './router'; export default function App() { //生成路由规则 const route=useRoutes(routes); return ( <div> <NavLink to="/home">Home</NavLink> <NavLink to="/about">About</NavLink> <div className="content"> //在要显示路由页面的地方挂载路由 {route} </div> </div> ) }
嵌套路由(子路由):
import React, { Fragment } from 'react' import { NavLink,Outlet} from 'react-router-dom' export default function Home() { return ( <Fragment> <NavLink to="/home/children">children</NavLink> <Outlet/> </Fragment> ) }
<Outlet>
:设置子路由的出口,即在何处渲染子路由
三、路由传参
1.传递params参数
注册路由时声明params
{ path: '/about /:id', element: <About/>, },
传递参数
<NavLink to={`/about/children/${id}>children</NavLink>
使用useParms()接收参数
import React from 'react' import { useParams} from 'react-router-dom' export default function Children() { const {id}=useParams(); return ( <div>About:{id}</div> ) }
2.传递search参数
注册
{ path: '/about', element: <About/>, },
传递参数
<NavLink to={`/about/children?id=${id}&message=${message}`}>children</NavLink>
使用 useSearchParams()
接收参数。该方法返回一个包含两个元素的数组:search
参数和修改 search
参数的方法。
import React from 'react' import { useSearchParams } from 'react-router-dom' export default function Children() { const [searchParams,setSearchParms]=useSearchParams(); //获取相对应的值 const id=searchParams.get('id'); const message=searchParams.get('message'); function change() { setSearchParams('id=2&message=ccc') } return ( <div>About {id}:{message} <button onClick={change}>Change search params</button> </div> ) }
3.传递state参数
注册
{ path: '/about', element: <About/>, },
传递参数
<NavLink to="/about/children" state={{id:id,message:message}}>children</NavLink>
使用 useLocation()
接收参数。该方法返回路由组件的 location
对象
import React from 'react' import { useParams} from 'react-router-dom' export default function Children() { const { state: { id,message }, } = useLocation(); return ( <div>{id}:{message}</div> ) }
useLocation()包含内容如下图:
四、路由跳转
方式一:NavLink标签的to属性
<NavLink to="/home">Home</NavLink>
方式二:useNavigate()
import React, { Fragment } from 'react' import { NavLink,Outlet,useNavigate} from 'react-router-dom' export default function Home() { const navigate=useNavigate(); const linkTo=()=>{ navigate("/home/children",{ replace:false, state:{ id:id, message:message } }) } const back=()=>{ //后退 navigate(1); //前进 //navigate(-1); } return ( <Fragment> <Button onClick={linkTo}>children</Button> <Button onClick={back}>children</Button> <Outlet/> </Fragment> ) }
useNavigate() 返回一个函数,调用该函数实现编程式路由导航。函数有两种参数传递方式。
第一种方式传递两个参数:路由和相关参数。参数只能设置 replace 和 state。想要传递 params 和 search 参数直接在路由带上。
第二种方式传递数字,代表前进或后退几步。
本文参考:https://blog.csdn.net/jiang7701037/article/details/131505912