学习目标
- react router 使用 ★ ★ ★ ★ ★
路由介绍
本教程直接说 react router, 对原生的路由感兴趣可以可以看一下这篇文章。 路由原理,目前主流框架原理都是这个。
现代的前端应用大多都是 SPA(单页应用程序),也就是只有一个 HTML 页面的应用程序。因为它的用户体验更好、对服务器的压力更小,所以更受欢迎。为了有效的使用单个页面来管理原来多页面的功能,前端路由应运而生。前端路由的功能:让用户从一个视图(页面)导航到另一个视图(页面)
- 前端路由是一套映射规则,在React中,是 URL路径 与 组件 的对应关系
- 使用 React 路由简单来说就是:配置路径和组件(配对)
安装路由 React Router
添加命令:
npm i -D react-router-dom
注意:本教程使用 React Router v6,如果您从 v5 升级,则需要使用 @latest 标志:
npm i -D react-router-dom@latest
项目文件结构
我们要创建多个文件配合一下演示路由,首先在 src
创建文件夹 pages
,创建几个文件:
src\pages\:
- Layout.js
- Home.js
- Blogs.js
- Contact.js
- NoPage.js (404配置页面)
每个文件都将包含一个非常基本的 React 组件。
// Home.js
const Home = () => {
return <h1>Home</h1>;
};
export default Home;
// Blogs.js
const Blogs = () => {
return <h1>博客</h1>;
};
export default Blogs;
// Contact.js
const Home = () => {
return <h1>联系我,公众号:程序员米粉。</h1>;
};
export default Contact;
// NoPage.js
const Home = () => {
return <h1>404</h1>;
};
export default NoPage;
基本用法
在项目里 index.js
文件配置路由。
看个例子:
import ReactDOM from "react-dom/client";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Layout from "./pages/Layout";
import Home from "./pages/Home";
import Blogs from "./pages/Blogs";
import Contact from "./pages/Contact";
import NoPage from "./pages/NoPage";
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="blogs" element={<Blogs />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
</BrowserRouter>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
示例解释
我们首先用 <BrowserRouter>
。
然后我们定义我们的 <Routes>
。 一个应用可以有多个 <Routes>
。 我们的基本示例仅使用一个。
<Route>
可以嵌套。第一个 <Route>
具有组件的路径 /
并呈现 Layout
组件。
嵌套 <Route>
可以继承并添加到父路由。因此 blogs
路径与父路径结合并变为 /blogs
。
Home
组件路由没有路径但有属性 index
。这将该路由为默认路由,即 /
。
设置 path 设置 *
任何未定义路径 。用来匹配 404
错误页面非常有用。
- element 路由配置组件
- path 表示匹配路径
- index 表示默认路由
*
表示匹配不到配置的路由,例如:404 页面
页面/组件
单独讲一下 Layout组件
, Layout
组件具有 <Outlet>
和 <Link>
元素。
<Outlet>
呈现当前选择的路线。
<Link>
用于设置 URL 并跟踪浏览历史记录。
每当我们链接到内部路径时,我们将使用 <Link>
代替 <a href="">
.
“layout route”是一个共享组件,它在所有页面上插入通用内容,例如导航菜单。
Layout.js
import { Outlet, Link, NavLink } from "react-router-dom";
const Layout = () => {
return (
<>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/blogs">Blogs</Link>
</li>
<li>
<NavLink to="/contact">Contact</NavLink>
</li>
</ul>
</nav>
<Outlet />
</>
)
};
export default Layout;
示例图1:
Router 路由详解
-
Router组件: 包裹整个应用,一般一个应用只使用一次。
-
两种常见的路由方式:
HashRouter
和BrowserRouter
-
HashRouter:使用 URL 的哈希值实现(http://localhost:3000/#/home)
- 原理:监听 window 的
hashchange
事件来实现的
- 原理:监听 window 的
-
(推荐)BrowserRouter:使用 H5 的 history API 实现(http://localhost:3000/home)
- 原理:监听 window 的
popstate
事件来实现的
- 原理:监听 window 的
import { BrowserRouter } from "react-router-dom";
嵌套路由
在平时开发中,通常都会碰到嵌套路由,在一个面,嵌套别的组件进去。例如后台管理系统。
以下路由就是一个典型的嵌套路由。
首先我们需要两步:
- 1.把子路由都嵌套到
Layout
根路由上。 - 2.渲染
Outlet
首先让子路 Home
、Blogs
、Contact
、NoPage
嵌套到 跟路由 Layout
上
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="blogs" element={<Blogs />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NoPage />} />
</Route>
</Routes>
当路由有子路由的时候,进行两件事:
- 它会嵌套 URL
("/" + "home"和"/" + "Blogs"、"/" + "Contact"、"/" + "NoPage")
- 当子路由匹配时,它将嵌套 UI 组件以进行共享布局(共享父路由页面布局, 示例图1:)
普通路由
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="blogs" element={<Blogs />} />
<Route path="contact" element={<Contact />} />
<Route path="*" element={<NoPage />} />
</Routes>
</BrowserRouter>
);
}
上述就是普通路由,移动端用的最多。
- exact 的说明, exact 表示精确匹配某个路径
- 一般来说,如果路径配置了 /, 都需要配置 exact 属性
Link 与 NavLink
Link
组件最终会渲染成a标签,用于指定路由导航
- to 属性,将来会渲染成a标签的 href 属性
Link
组件无法实现导航的高亮效果
NavLink
组件,一个更特殊的 Link
组件,可以用用于指定当前导航高亮。其实就是在 Link
基础上再加多了2个功能。
- to 属性,用于指定地址,会渲染成 a 标签的 href 属性
- activeClass: 用于指定高亮的类名,默认
active
- exact: 精确匹配,表示必须精确匹配类名才生效
以编程方式导航
用 js方式跳转路由方式,例如登录的场景,登录成功跳转某个页面。
import { useNavigate } from 'react-router-dom'
import { Link } from "react-router-dom"
const Home = () => {
let navigate = useNavigate()
return (
<div>
<button
onClick={() => {
navigate('/blogs')
}}
>
登录
</button>
<Link to="/blogs"> 博客 </Link >
</div>
)
}
export default Home
我们使用 useNavigate
方法,登录成功后可以跳转到页面 Blogs
。当然 Link
也是可以同样的跳转效果。
传递/获取参数
需要再配置路由的时候配置参数
export default function App() {
return (
<BrowserRouter>
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="blogs/:id" element={<Blogs />} />
</Routes>
</BrowserRouter>
);
}
主要配置 path = "路由名称/ :参数"
<Route path="blogs/:id" element={<Blogs />} />
Home.js:
import { useNavigate } from 'react-router-dom'
import { Link } from 'react-router-dom'
const Home = () => {
let navigate = useNavigate()
let id = 123
return (
<div>
<button
onClick={() => {
navigate(`/blogs/${id}`)
}}
>
登录
</button>
<Link to={`/blogs/${id}`}> 博客 </Link>
</div>
)
}
export default Home
navigate
方法或者 Link
皆可传递参数。跳转的下一个页面使用 useParams
负责接收参数。
Blogs.js:
import { useParams } from 'react-router-dom'
const Blogs = () => {
let params = useParams()
return <h1>博客文章。获取到参数id: {params.id}</h1>
}
export default Blogs
使用方法 useParams
获取传递参数。
结语
希望看完这篇文章对你有帮助,文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你,
🌹🌹🌹欢迎点赞🌹🌹🌹,
🌹🌹🌹关注🌹🌹🌹,
后续会输出更好的分享。
欢迎关注公众号:【程序员米粉】
公众号分享开发编程、职场晋升、大厂面试经验