-
路由介绍
- 因为SPA 页面,只有一个 HTMl 页面的应用程序, 用户的体验感更好,对于服务器的访问压力也更加好;
- 前端路由是一套映射规则,在 React 中,是 浏览器的URL 路径与组件的一 一对应关系;
-
一个路由就是一个映射关系(key:value) key为路径, value可能是function或component
-
路由功能
- 让用户能够从一个视图通过交互导航到另外的视图;
-
react-router-dom v6 版本
- 安装
- 如果项目中还没有安装 React Router 则可以进行如下 NPM 安装,默认安装的就是 v6 版本 npm i react-router-dom
-
npm i react-router-dom
- 如果项目中还没有安装 React Router 则可以进行如下 NPM 安装,默认安装的就是 v6 版本 npm i react-router-dom
- 安装
-
react-router-dom 路由模式
-
模式 实现方式 路由URL表现 HashRouter 监听url hash值实现 http://localhost:3000/#/about BrowerRouter h5的 history.pushState API实现 http://localhost:3000/about - Link:用于指定导航链接,完成声明式的路由跳转 类似于 Vue 中 <router-link />(渲染到 DOM 中它其实就是一个 a 链接):<Link to="your path"></Link>
- Routes:提供一个路由出口,组件内部会存在多个内置的 Route 组件,满足条件的路由会被渲染到组件内部,所以 Route 组件必须被Routes组件包裹才能展示(类比 vue 中的 router-view):
<Routes>
<Route path="your path" element={<Home />}></Route>
</Routes> - Route:用于定义路由路径 path 和渲染组件 element 的对应关系 [element:因为 react 体系内把组件叫做 react element]: 第三点有介绍
-
-
react-router-dom V6 常用组件的介绍
- <BrowserRouter>与<HashRouter>
<BrowserRouter> 组件用于包裹整个需要使用到路由组件的应用区域(一般用于包裹整个 <App />),它也表示当前路由模式为 BrowserRouter 模式; - <BrowserRouter> 之外还可以使用 <HashRouter> 组件,用法相同,它表示当前路由模式为 HashRouter(具体表现为页面地址栏中会出现一个 /# )
- <BrowserRouter>与<HashRouter>
- 代码实例
-
import { BrowserRouter, Routes, Route, Link, useNavigate, } from "react-router-dom"; function Home() { return <p>首页组件Home</p>; } function About() { // 用于函数式组件,用于类组件可能会报错 const navigate = useNavigate(); function goBack() { navigate("/"); } return ( <div> <div style={{ width: "200px", height: "20px", backgroundColor: "#000", cursor: "pointer", color: "white", }} onClick={goBack} > 点击跳转回Home 组件 </div> 关于页面About </div> ); } // 非hash模式的路由,一般 可以放在index.js 中,直接包裹 App 组件也行的 /* * * const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <<BrowserRouter> <App /> </BrowserRouter> ); * */ { /* 所有的路由配置均在 BrowserRouter 内部 */ } function App() { return ( <BrowserRouter> <div className="App"> {/* 指定跳转的组件,to 用来配置路由地址 */} <Link to="/">首页</Link> <br /> <Link to="/about">关于</Link> {/* 路由出口:路由对应的组件会在这里进行渲染, 同时这个 Routes 用来 替换曾经的 Switch */} <Routes> {/* 指定路由路径和组件的对应关系:path 代表路径,element 代表对应的组件,它们成对出现 */} <Route path="/" element={<Home />}></Route> <Route path="/about" element={<About />}></Route> </Routes> </div> </BrowserRouter> ); } export default App;
-
-
导航方式
- 声明式导航
- 使用 <Link to="/">跳转</Link> 的方式是:声明式导航,或者 NavLink(相当于Link的加强版)方式
- 编程式导航
- 函数式组件
function About() { // 用于函数式组件,用于类组件可能会报错 const navigate = useNavigate(); function goBack() { navigate("/"); } return ( <div> <div style={{ width: "200px", height: "20px", backgroundColor: "#000", cursor: "pointer", color: "white", }} onClick={goBack} > 点击跳转回Home 组件 </div> </div> ); }
- 类组件中:
由于react-router-dom升级到6版本后,无法按照this.props.history.push()进行编程式导航,此时props会提示是空值,v6文档里把路由组件默认接受的三个属性给移除了,官网文档里给出的解决方案是使用useNavigate()这个hook,但是hook只能存在于无状态组件,无法用在类组件中,通过Navigate这个标签来实现路由跳转,但官方其实也不推荐,更推荐去使用hook。
- 函数式组件
-
获取路由参数
- useParams 获取动态路由的值
- useSearchParams 获取查询字符串的值
- useLocation 获取上一个页面传递进来的 state 参数 v5、v6一样
-
import { useEffect } from "react"; import { BrowserRouter, Routes, Route, Link, useNavigate, useParams, useSearchParams, useLocation, } from "react-router-dom"; function Home() { const navigate = useNavigate(); // 动态路由 function dynamicRoutes() { navigate(`/about/${1}/${2}`); } // useSearchParams 传递参数 function searchPassParams() { navigate(`/about?id=1&search=2`); } // location 方式传递参数 function locationRouts() { let obj = { a: 1, b: 2, c: 3, }; navigate(`/about`, { state: obj }); // 特点: // 1、BrowserRouter(history)模式下,刷新页面参数不消失,参数不会在地址栏显示,因为state保存在 history对象中 // 2、HashRouter(hash)模式下,刷新页面参数消失!!!参数不会在地址栏显示 } return ( <div> <div onClick={dynamicRoutes}>动态路由方式 /about/:id/:key</div> <div onClick={searchPassParams}>search 方式传递参数</div> <div onClick={locationRouts}>location 方式传递参数</div> <p>首页组件Home</p> </div> ); } function About() { const navigate = useNavigate(); const params = useParams(); // 动态路由获取参数 { id: 1, key: 2} 具体看你怎么, 传一个也是可以的 const [searchParams, setSearchParams] = useSearchParams(); const location = useLocation(); function goBack() { navigate("/"); } // 动态路由传递参数 useEffect(() => { console.log("/about/:id 动态路由", params); }, [params]); // searchParams 传递参数 useEffect(() => { console.log( "searchParams 传递参数,查看 search 参数值", searchParams.get("search") ); // setSearchParams; 用来设置 url 的 key 和 参数 // setSearchParams("key=1"); }, [searchParams]); // useLocation 接受参数 useEffect(() => { console.log("obj 传递的参数", location.state); }, [location]); return ( <div> <div style={{ width: "200px", height: "20px", backgroundColor: "#000", cursor: "pointer", color: "white", }} onClick={goBack} > 点击跳转回Home 组件 </div> 关于页面About </div> ); } function App() { return ( <BrowserRouter> <div className="App"> <Link to="/">首页</Link> <br /> <Link to="/about">关于</Link> <Routes> <Route path="/" element={<Home />}></Route> {/* 动态路由传递的方式, 和 Vue 大同小异 */} {/* <Route path="/about/:id/:key" element={<About />}></Route> */} {/* useSearchParams \ useLocation 传递参数*/} <Route path="/about" element={<About />}></Route> </Routes> </div> </BrowserRouter> ); } export default App;
- 总结
- state传参:BrowserRouter(history)模式下,刷新页面不消失;而
- HashRouter(hash)模式下,刷新页面会消失,但都不会暴露在url中
- params传参(动态路由):可读性高,便于维护,当另一个页面一定需要某数据时,推荐使用
- search传参:会暴露在url中,刷新页面不会消失,但取数据时,需处理
- 声明式导航
-
react-router-dom 路由嵌套
- 嵌套路由的 path 可以不用写父级,会直接拼接;
- 由于 /about/Aboutdetail 的匹配度大于 /about/* ,所以输入精确地址,会精确匹配,而不是匹配到动态路由;
- 嵌套路由必须在父级追加 Outlet 组件,作为子级组件的占位符,类似于 vue-router 中的 router-view 。
- 实例代码
import { useEffect } from "react"; import { BrowserRouter, Routes, Route, Link, useNavigate, Outlet, } from "react-router-dom"; function Home() { return ( <div> <p>首页组件Home</p> </div> ); } function About() { const naviate = useNavigate(); function goAboutdetail() { naviate("/about/aboutDetail"); } return ( <div> <div>关于页面About</div> <div onClick={goAboutdetail}>点击跳转到到 Aboutdetail 组件 </div> <Outlet></Outlet> </div> ); } function Aboutdetail() { return <div>Aboutdetail 子页面</div>; } function App() { return ( <BrowserRouter> <div className="App"> <Link to="/">首页</Link> <br /> <Link to="/about">关于</Link> <Routes> <Route path="/" element={<Home />}></Route> <Route path="/about" element={<About />}> <Route path="aboutDetail" element={<Aboutdetail />}></Route> </Route> </Routes> </div> </BrowserRouter> ); } export default App;
-
react-router-dom 使用 useRoutes API 对路由进行集中式管理
-
import { lazy } from "react"; import { Link, useNavigate, useRoutes, Outlet, Navigate, } from "react-router-dom"; function Home() { return ( <div> <p>首页组件Home</p> </div> ); } function About() { const naviate = useNavigate(); function goAboutdetail() { naviate("/about/aboutDetail"); } return ( <div> <div>关于页面About</div> <div onClick={goAboutdetail}>点击跳转到到 Aboutdetail 组件 </div> <Outlet></Outlet> </div> ); } function Aboutdetail() { return <div>Aboutdetail 子页面</div>; } function Detail() { return <div>About 子页面</div>; } const routes = [ { path: "/", element: <Navigate to={"/home"} />, }, { path: "/home", element: <Home></Home>, }, { path: "/about", element: <About />, children: [ { index: true, path: "aboutDetail", element: <Aboutdetail />, }, { path: "detail", element: <Detail />, }, ], }, ]; function App() { return ( <div> <div className="App"> <Link to="/">首页</Link> <br /> <Link to="/about">关于</Link> </div> {useRoutes(routes)} </div> ); } export default App;
- 设置默认二级路由设置需要注意的地方,
-
场景:需要默认显示二级路由,这时候需要默认二级路由设置
方法:添加index属性,再把他自己的path干掉
-
<Route index element={<detail/>}></Route>
- 同样的,useRoutes 中集中管理路由也把 path 去掉,就可以实现 默认显示的组件
-
-
react 路由详解, react-router-dom V6
最新推荐文章于 2024-04-18 03:49:53 发布