React Router基础:BrowserRouter、Routes,以及Route和Link详解
了解在 React Router 中 BrowserRouter、Routes、Route 和 Link 的各自功能,它们如何在同一个应用中协同工作,以及如何回答关于它们的常见面试问题。
大多数 React 应用很快就需要多个页面,比如首页、关于我们、产品介绍和联系我们。React 本身并不支持 URL 概念,因此将地址与页面对应的工作由相关库来完成,通常是 React Router。它包含四个核心组件,可覆盖大多数常见路由场景:<BrowserRouter>、<Routes>、<Route> 和 <Link>。一旦了解每个组件的功能及其嵌套方式,你就能构建多页面的单页应用,并在面试中清晰解释其原理。
BrowserRouter:连接 React 与 URL
<BrowserRouter> 就是路由器本身。它通过浏览器的 History API 实现客户端路由,使渲染的界面与地址栏保持同步,而无需向服务器请求新文档。
当您的应用需要为不同页面提供独立的URL,但整体仍表现为一个页面时,请使用此方法,例如:
/
/about
/products
/contact
设置方式就是将组件树包裹起来;所有需要路由处理的元素都必须位于该结构内部:
import { BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter>
{/* Application routes */}
</BrowserRouter>
);
}
通常只需在根节点处配置一次。一个实际后果是:由于像 /about 这样的路径属于真实URL,您的服务器必须为所有这些路径提供相同的 index.html,否则在访问 /about 时就会返回服务器404错误。
路由决定要渲染的内容
<Routes> 是用于存放路由定义的容器。每当页面地址发生变化时,它会将当前URL与其中的路由项进行比较,并渲染匹配的那一项。每当需要由React Router而非手动编写的条件判断来决定显示哪个页面时,请使用此方法:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/products" element={<Products />} />
</Routes>
这里,一个 <Routes> 元素负责处理所有三条路径。它会选择最匹配的路径而非列表中的第一个,因此几乎无需担心顺序问题。
路由将一个路径映射到一个元素
每个 <Route> 都会将一个 URL 路径与要显示的组件对应起来,就像查找表中的一条记录:
/about → About component
/products → Products component
对于每个需要渲染特定内容的 URL,都需要添加一个对应的元素。关键的属性是 path 和 element:
<Route
path="/about"
element={<About />}
/>
根据这样的定义,访问该地址时:
/about
会促使 React Router 进行渲染:
<About />
请注意,element 接收的是已渲染的元素(如 <About />),而非组件引用,因此可以直接传递属性。多个路由的组合形式如下:
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
如果没有匹配的路径,此块中的内容将不会显示;通常使用通用的 path="*" 路由来展示“未找到”页面。
无需重新加载即可跳转
可在应用保持加载状态的情况下将用户切换到不同路由。它在 DOM 中渲染一个普通的 标签,但会拦截点击事件并让 React Router 处理导航。可将其用于导航栏等内部跳转场景:
import { Link } from "react-router-dom";
function Navbar() {
return (
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
);
}
点击 关于 会更新 URL, 会重新进行评估,这样无需刷新浏览器即可显示关于页面,从而保持共享的布局和内存中的状态。对于外部网站,使用普通的 标签仍然是正确的做法。
将四者结合使用
一个最简的完整配置(Home、About和Contact在其他地方定义):
import {
BrowserRouter,
Routes,
Route,
Link
} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</BrowserRouter>
);
}
链接与<Routes>块都位于<BrowserRouter>内部,属于同级元素:导航会在每个页面上持续显示,只有<Routes>区域的内容会发生变化。其层级结构简述如下:
BrowserRouter
↓
Routes
↓
Route
↓
Component
<Link>位于该链的旁边,是用户点击以更改URL的控制元素。这些示例来自react-router-dom;较新的大版本也提供了react-router包中的这些API,因此请查阅对应版本的文档。
面试问题
- 什么是
<BrowserRouter>?它是一种实现客户端路由的路由器,能够使用户界面与浏览器URL保持同步。
<Routes>与<Route>有何区别?<Routes>是用于匹配URL的容器;每个<Route>定义一个路径以及要渲染的元素。<Link>与<a>有何不同?<Link>可在客户端直接跳转而无需完全重新加载页面;而普通的<a>则会迫使浏览器再次加载该URL对应的页面。<Link>?因为它能使应用保持单页应用的结构,避免不必要的整页重新加载。<Route>能否在没有<BrowserRouter>的情况下使用?通常不能:路由组件必须要在如<BrowserRouter>这样的路由器上下文中进行渲染。核心要点
<BrowserRouter>用于在根层级实现一次路由配置。<Routes>负责管理路由并渲染匹配的页面。<Route>将URL映射到对应的组件。<Link>可在不重新加载页面的情况下在路由之间切换。
嵌套路由、动态路径段、受保护的路由以及导航钩子都基于这一相同模型构建。关于React在路由变化时如何决定重新渲染的内容,可参阅React重新渲染、状态与钩子的思维模型构建。
相关阅读
- 构建 React 的思维模型:Reconciliation、State 与 Hooks — 了解 React 核心概念——Reconciliation、组件、props、state 和 hooks——背后的原理,从而培养直觉而非死记硬背 API。
- React 19.2详解:Activity、useEffectEvent 与静态渲染 — 了解 React 19.2 中新增的 Activity 组件、useEffectEvent 钩子以及部分静态渲染功能如何解决现代 UI 中的隐性性能问题。