React Router 基础入门与安装
1. React Router 简介
React Router 是用于在 React 应用中进行路由管理的核心库。在单页应用(SPA)的开发中,路由起着至关重要的作用。它使得应用能够根据不同的 URL 展示不同的 UI 内容,为用户提供类似于多页应用的导航体验,同时又不会因为页面的重新加载而导致性能问题。
React Router 提供了声明式的路由语法,这意味着开发者可以像声明 React 组件一样声明应用的路由结构。这种声明式的方式使得路由配置更加直观,易于理解和维护。例如,通过简单的配置,我们可以指定当 URL 为 /home
时,展示 Home
组件;当 URL 为 /about
时,展示 About
组件。
2. 安装 React Router
在开始使用 React Router 之前,我们需要将其安装到项目中。React Router 有不同的版本,目前较新的版本是 React Router v6。安装步骤如下:
2.1 创建 React 项目(如果尚未创建)
如果还没有 React 项目,可以使用 create - react - app
工具快速创建一个新的 React 项目。首先确保你已经全局安装了 create - react - app
:
npm install -g create - react - app
然后创建项目:
create - react - app my - react - app
cd my - react - app
2.2 安装 React Router
在项目目录下,使用 npm
或 yarn
安装 React Router:
# 使用 npm
npm install react - router - dom
# 使用 yarn
yarn add react - router - dom
这里我们安装的是 react - router - dom
,它是 React Router 用于 web 应用的特定版本。如果是开发 React Native 应用,则需要安装 react - router - native
。
3. 基本路由配置
安装完成后,我们就可以开始配置基本路由了。以下是一个简单的示例,展示如何在 React 应用中配置两个基本路由:Home
和 About
。
3.1 创建组件
首先,创建 Home
和 About
组件。在 src
目录下,创建 components
文件夹,并在其中创建 Home.js
和 About.js
文件。
Home.js
import React from'react';
const Home = () => {
return (
<div>
<h1>Home Page</h1>
<p>This is the home page of our React application.</p>
</div>
);
};
export default Home;
About.js
import React from'react';
const About = () => {
return (
<div>
<h1>About Page</h1>
<p>This is the about page where you can learn more about our application.</p>
</div>
);
};
export default About;
3.2 配置路由
在 src
目录下的 App.js
文件中,导入并配置路由。在 React Router v6 中,主要使用 BrowserRouter
、Routes
和 Route
组件。
import React from'react';
import { BrowserRouter as Router, Routes, Route } from'react - router - dom';
import Home from './components/Home';
import About from './components/About';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
在上述代码中:
BrowserRouter
是整个应用路由的顶层容器,它会监听浏览器地址栏的变化,并根据路由配置渲染相应的组件。这里我们使用了别名Router
,这是一种常见的写法。Routes
组件用于定义一组路由。它会根据当前 URL 匹配到合适的Route
并渲染对应的组件。Route
组件定义了具体的路由规则。path
属性指定了 URL 路径,element
属性指定了该路径对应的要渲染的 React 组件。
4. 嵌套路由
在实际应用中,我们经常会遇到嵌套路由的情况。例如,一个博客应用可能有文章列表页面,每个文章又有自己的详情页面,而且这些详情页面可能还包含评论、相关文章等子页面。
4.1 创建嵌套组件
假设我们有一个 Blog
组件,它包含文章列表,并且每个文章有详情页。我们先创建 Blog
组件和 Article
组件。
Blog.js
import React from'react';
const Blog = () => {
return (
<div>
<h1>Blog Page</h1>
<p>This is the blog page with a list of articles.</p>
</div>
);
};
export default Blog;
Article.js
import React from'react';
const Article = () => {
return (
<div>
<h1>Article Page</h1>
<p>This is the page for a specific article.</p>
</div>
);
};
export default Article;
4.2 配置嵌套路由
在 App.js
中配置嵌套路由:
import React from'react';
import { BrowserRouter as Router, Routes, Route } from'react - router - dom';
import Home from './components/Home';
import About from './components/About';
import Blog from './components/Blog';
import Article from './components/Article';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />}>
<Route path=":articleId" element={<Article />} />
</Route>
</Routes>
</Router>
);
}
export default App;
在上述代码中,/blog
路由下嵌套了一个动态路由 :articleId
。这里的 :articleId
是一个动态参数,它可以匹配任何字符串。例如,/blog/123
会匹配到这个路由,并且可以通过 useParams
钩子函数获取到 articleId
的值为 123
。
5. 路由导航
路由配置完成后,我们需要提供导航链接,让用户能够在不同的路由之间切换。在 React Router 中,可以使用 Link
组件来创建导航链接。
5.1 使用 Link 组件
在 App.js
中添加导航链接:
import React from'react';
import { BrowserRouter as Router, Routes, Route, Link } from'react - router - dom';
import Home from './components/Home';
import About from './components/About';
import Blog from './components/Blog';
import Article from './components/Article';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/blog">Blog</Link></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />}>
<Route path=":articleId" element={<Article />} />
</Route>
</Routes>
</div>
</Router>
);
}
export default App;
在上述代码中,我们在 nav
标签内使用 Link
组件创建了到 Home
、About
和 Blog
页面的链接。Link
组件的 to
属性指定了链接的目标路径。
5.2 NavLink 组件
NavLink
是 Link
的一个增强版本,它可以在链接对应的路由被激活时添加特定的样式。例如,我们可以让当前激活的导航链接有不同的颜色。
import React from'react';
import { BrowserRouter as Router, Routes, Route, NavLink } from'react - router - dom';
import Home from './components/Home';
import About from './components/About';
import Blog from './components/Blog';
import Article from './components/Article';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><NavLink to="/" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Home</NavLink></li>
<li><NavLink to="/about" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>About</NavLink></li>
<li><NavLink to="/blog" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Blog</NavLink></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />}>
<Route path=":articleId" element={<Article />} />
</Route>
</Routes>
</div>
</Router>
);
}
export default App;
在上述代码中,NavLink
的 style
属性接受一个函数,该函数根据 isActive
参数来决定是否应用特定的样式。当 isActive
为 true
时,即当前链接对应的路由被激活时,文字颜色变为蓝色。
6. 获取路由参数
在动态路由中,获取路由参数是非常常见的需求。例如,在文章详情页,我们需要根据文章的 ID 获取具体的文章内容。在 React Router v6 中,可以使用 useParams
钩子函数来获取路由参数。
6.1 使用 useParams
在 Article.js
组件中获取 articleId
参数:
import React from'react';
import { useParams } from'react - router - dom';
const Article = () => {
const { articleId } = useParams();
return (
<div>
<h1>Article Page - {articleId}</h1>
<p>This is the page for article with ID: {articleId}</p>
</div>
);
};
export default Article;
在上述代码中,通过 useParams
钩子函数获取到 articleId
参数,并将其显示在页面上。
7. 路由重定向
有时候,我们需要将用户从一个路由重定向到另一个路由。例如,当用户访问一个旧的 URL 时,我们希望将其重定向到新的 URL。在 React Router v6 中,可以使用 Navigate
组件进行重定向。
7.1 使用 Navigate 组件
假设我们有一个旧的 /old - home
路由,现在希望将其重定向到 /
路由。在 App.js
中配置:
import React from'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from'react - router - dom';
import Home from './components/Home';
import About from './components/About';
import Blog from './components/Blog';
import Article from './components/Article';
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><NavLink to="/" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Home</NavLink></li>
<li><NavLink to="/about" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>About</NavLink></li>
<li><NavLink to="/blog" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Blog</NavLink></li>
</ul>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/blog" element={<Blog />}>
<Route path=":articleId" element={<Article />} />
</Route>
<Route path="/old - home" element={<Navigate to="/" replace />} />
</Routes>
</div>
</Router>
);
}
export default App;
在上述代码中,当用户访问 /old - home
时,Navigate
组件会将其重定向到 /
路由。replace
属性表示在重定向时使用 replaceState
而不是 pushState
,这样在浏览器历史记录中不会留下 /old - home
的记录,用户点击后退按钮时不会回到 /old - home
。
8. 路由懒加载
随着应用的增长,打包后的文件大小也会增加。为了提高应用的加载性能,我们可以使用路由懒加载,即只有在需要的时候才加载相应的路由组件。在 React Router v6 中,可以结合 React.lazy 和 Suspense 来实现路由懒加载。
8.1 配置路由懒加载
在 App.js
中配置懒加载:
import React, { lazy, Suspense } from'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from'react - router - dom';
const Home = lazy(() => import('./components/Home'));
const About = lazy(() => import('./components/About'));
const Blog = lazy(() => import('./components/Blog'));
const Article = lazy(() => import('./components/Article'));
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><NavLink to="/" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Home</NavLink></li>
<li><NavLink to="/about" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>About</NavLink></li>
<li><NavLink to="/blog" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Blog</NavLink></li>
</ul>
</nav>
<Routes>
<Route path="/" element={
<Suspense fallback={<div>Loading...</div>}>
<Home />
</Suspense>
} />
<Route path="/about" element={
<Suspense fallback={<div>Loading...</div>}>
<About />
</Suspense>
} />
<Route path="/blog" element={
<Suspense fallback={<div>Loading...</div>}>
<Blog />
</Suspense>
}>
<Route path=":articleId" element={
<Suspense fallback={<div>Loading...</div>}>
<Article />
</Suspense>
} />
</Route>
<Route path="/old - home" element={<Navigate to="/" replace />} />
</Routes>
</div>
</Router>
);
}
export default App;
在上述代码中,使用 React.lazy
函数将组件的导入延迟到实际需要渲染该组件时。Suspense
组件用于在组件加载时显示一个加载提示(这里是 Loading...
)。
9. 路由守卫
路由守卫可以在路由切换之前或之后执行一些逻辑,例如验证用户是否登录、检查权限等。在 React Router v6 中,虽然没有像 Vue Router 那样直接提供路由守卫的功能,但我们可以通过一些自定义逻辑来实现类似的效果。
9.1 实现简单的路由守卫
假设我们有一个需要用户登录才能访问的 Dashboard
组件。我们可以创建一个自定义的 PrivateRoute
组件来实现路由守卫的功能。
PrivateRoute.js
import React from'react';
import { Routes, Route, Navigate } from'react - router - dom';
const isLoggedIn = () => {
// 这里可以实现实际的登录验证逻辑,例如检查 localStorage 中是否有 token
return true;
};
const PrivateRoute = ({ children }) => {
if (!isLoggedIn()) {
return <Navigate to="/login" replace />;
}
return children;
};
export default PrivateRoute;
然后在 App.js
中使用 PrivateRoute
:
import React, { lazy, Suspense } from'react';
import { BrowserRouter as Router, Routes, Route, Navigate } from'react - router - dom';
import PrivateRoute from './components/PrivateRoute';
const Home = lazy(() => import('./components/Home'));
const About = lazy(() => import('./components/About'));
const Blog = lazy(() => import('./components/Blog'));
const Article = lazy(() => import('./components/Article'));
const Dashboard = lazy(() => import('./components/Dashboard'));
function App() {
return (
<Router>
<div>
<nav>
<ul>
<li><NavLink to="/" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Home</NavLink></li>
<li><NavLink to="/about" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>About</NavLink></li>
<li><NavLink to="/blog" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Blog</NavLink></li>
<li><NavLink to="/dashboard" style={({ isActive }) => ({ color: isActive? 'blue' : 'black' })}>Dashboard</NavLink></li>
</ul>
</nav>
<Routes>
<Route path="/" element={
<Suspense fallback={<div>Loading...</div>}>
<Home />
</Suspense>
} />
<Route path="/about" element={
<Suspense fallback={<div>Loading...</div>}>
<About />
</Suspense>
} />
<Route path="/blog" element={
<Suspense fallback={<div>Loading...</div>}>
<Blog />
</Suspense>
}>
<Route path=":articleId" element={
<Suspense fallback={<div>Loading...</div>}>
<Article />
</Suspense>
} />
</Route>
<Route path="/dashboard" element={
<PrivateRoute>
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
</PrivateRoute>
} />
<Route path="/old - home" element={<Navigate to="/" replace />} />
</Routes>
</div>
</Router>
);
}
export default App;
在上述代码中,PrivateRoute
组件会检查用户是否登录(通过 isLoggedIn
函数)。如果用户未登录,就会将其重定向到 /login
路由。这样就实现了一个简单的路由守卫功能。
通过以上内容,我们对 React Router 的基础入门与安装进行了详细的介绍,包括基本路由配置、嵌套路由、路由导航、获取路由参数、路由重定向、路由懒加载以及路由守卫等重要知识点。这些内容是构建复杂 React 单页应用路由系统的基础,熟练掌握它们将有助于开发者创建出更加高效、用户体验良好的应用。