在 React 生态中,单页应用(SPA)的开发离不开 "路由" 这一关键技术。它能让我们在不刷新页面的情况下,实现组件间的灵活切换,打造出类多页应用的体验。而 React Router 就是 React 世界里处理路由的核心工具集。在尝试手写 React Router 之前,我们需要先深入理解它的核心概念与运作逻辑。
用简单示例认识 React Router
在 React 里做单页应用,就像在一个大网页里装很多小 "页面"(其实是不同组件)。要实现点个链接,不刷新页面就切换这些小 "页面",就得靠路由。React Router 就是干这个活儿的工具。在自己动手写 React Router 之前,咱们先结合示例,把它的关键知识和用法搞明白。
一、路由是干啥的
单页应用就一个 HTML 文件,但里面会有好几个不同的 "页面"(用不同组件展示)。路由要做两件事:
-
不同网址对应不同组件:比如网址是
/home
就显示首页组件,/about
就显示关于页组件。 -
切换时不刷新页面:点来点去,浏览器不会整个重新加载,体验更流畅。
能做到这两点的,就是路由。
二、React Router 都有啥
React Router 不是一个单独的库,是一套工具:
-
react-router
:核心库,里面是路由最基础的逻辑,像怎么匹配路径、怎么传数据这些。 -
react-router-dom
:基于核心库,专门给浏览器用的,能处理浏览器地址栏这些事儿,我们开发网页应用主要用它。
先给项目装上它,后面示例要用:
bash
npm install react-router-dom
三、两种路由模式
路由得看网址来选组件,有两种看网址的方式,咱们结合示例里的配置来理解。
(一)哈希路由(HashRouter)
看网址里 #
后面的内容,比如 https://xxx.com/#/home
里的 #/home
。
为啥用哈希?因为 #
后面的内容变了,浏览器不会刷新页面,所以兼容性很好,老浏览器也能用。如果示例里想用这种模式,只要把代码里的 BrowserRouter
换成 HashRouter
就行。
(二)浏览器历史路由(BrowserRouter)
HTML5 出来后,浏览器有了新能力,能改网址还不刷新页面。
浏览器的历史记录是像栈一样存着的,还有专门的 API:
-
history.length
:看看历史记录有多少条。 -
history.pushState
:往历史记录里加一条新的。 -
history.replaceState
:替换当前的历史记录。
BrowserRouter 就是用这些 API,看网址里的路径(比如 https://xxx.com/home
里的 /home
)来选组件。这种模式的网址没有 #
,看起来更干净,但得浏览器支持 HTML5 才行。咱们下面的示例就用这种模式。
四、核心组件是啥作用(附示例)
React Router 有几个关键组件,各司其职,咱们直接用一个 "首页 + 关于页" 的示例,看它们怎么配合工作:
jsx
import React from 'react';
// 从 react-router-dom 里引入需要的组件
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
// 1. 先写两个要切换的"页面"组件
function Home() {
return <h1>我是首页</h1>;
}
function About() {
return <h1>我是关于页</h1>;
}
// 2. 根组件里配置路由
function App() {
return (
{/* (1)Router 组件:包裹整个应用,选 BrowserRouter 模式 */}
<Router>
<div style={{ padding: '20px' }}>
{/* (2)Link 组件:生成导航链接,点它换地址不刷新 */}
<Link to="/" style={{ marginRight: '20px' }}>首页</Link>
<Link to="/about">关于页</Link>
<hr />
{/* (3)Switch 组件:匹配到第一个 Route 就停,不浪费性能 */}
<Switch>
{/* (4)Route 组件:路径和组件的"匹配规则" */}
{/* exact 表示精确匹配根路径 /,不然 /about 也会蹭到 / 的匹配 */}
<Route exact path="/">
<Home /> {/* 路径匹配,就显示 Home 组件 */}
</Route>
{/* 匹配 /about 路径,显示 About 组件 */}
<Route path="/about">
<About />
</Route>
</Switch>
</div>
</Router>
);
}
export default App;
运行这个示例,点击 "首页""关于页" 链接,就能在不刷新页面的情况下切换组件了。下面咱们拆解每个组件的作用:
(一)Router 组件
它自己不显示东西,主要干两件事:
-
选路由模式:示例里用
BrowserRouter
(还起了个别名Router
),也能换成HashRouter
。 -
传数据:给下面的
Route
、Link
这些组件传递路由相关的信息,让它们能正常工作。
一般用一个 Router 把整个应用包起来,这样所有后代组件都能用上路由功能。
(二)Link 组件
专门用来做导航链接的。普通的 <a href="/about">
点击会刷新页面,而 Link
的 to
属性指定目标地址,点击后只会改变地址栏的内容,不会刷新页面,正好符合单页应用的需求。
(三)Route 组件
路由的 "核心匹配器",负责把 "路径" 和 "组件" 绑在一起。关键属性看示例就能懂:
path
:要匹配的网址路径,比如/
对应首页,/about
对应关于页。exact
:示例里给/
加了这个属性,意思是 "必须完全匹配"。如果不加,访问/about
时,因为/about
包含/
,会先匹配到/
对应的 Home 组件,就错了。- 组件内容:
Route
标签里包的组件(比如<Home />
),就是路径匹配后要显示的内容。
(四)Switch 组件
像个 "筛选器",包裹一堆 Route
组件时,会按顺序逐个匹配,一旦找到第一个符合条件的 Route
,就会渲染它,并且停止后面的匹配。示例里如果没有 Switch
,当路径是 /about
时,虽然会匹配到 /about
对应的 About 组件,但也会因为 /
没有 exact
而匹配到 Home 组件,导致两个组件一起显示,这就乱了。
五、下一步:自己手写 React Router
现在咱们通过示例,清楚了 React Router 是怎么用 Router
定模式、Link
做导航、Route
配匹配、Switch
优化筛选,最终实现单页应用路由的。接下来,咱们就动手拆解这些逻辑,一步步写出属于自己的 React Router,把这些 "用起来" 的知识,变成 "能实现" 的能力~