路由
你可能已经意识到了一个问题,我们的应用现在只有一个页面,这显然是不够的。在这一节中,我们将学习如何使用 React Router
来实现页面路由。
什么是路由
路由
是指根据不同的 URL
地址,展示不同的内容。比如说:
这些不同的 URL
地址对应着不同的页面,这就是 路由
的概念。
React Router
在 React
中,我们可以使用 React Router
来快速实现路由,通过 VSCode
打开终端,输入以下命令来安装 React Router
:
创建一个页面
首先,在 src
目录下新建一个 pages
文件夹,然后在这个文件夹中新建一个 HelloWorld.tsx
文件,用于存放我们之前的 main
组件。尝试着自己完成这个步骤,如果遇到问题,可以查看下面的代码示例。
现在,我们已经有了一个页面,接下来,让我们开始配置路由。
配置 main.tsx
在我们开始之前,让我们先备份一下当前的 main.tsx
文件,让我们重命名为 main-helloWorld.tsx
。然后,新建一个 main.tsx
文件,我们可以在这个文件中写入以下代码:
让我们来逐行理解这段代码:
BrowserRouter
和Routes
是React Router
提供的一个组件,用于包裹整个应用,在这里我们直接使用就好。Route
则用于配置路由,index
表示默认路由,path
表示路径,element
表示对应的组件。- 这里我们可以看到几种特殊的用法:
index
表示默认路由path="/hello"
表示路径为/hello
的路由path="/hello/*"
表示/hello
开头的所有路径的路由。这里的*
是通配符,表示所有路径。path="/hello/:id"
表示/hello
开头的所有路径的路由,其中:id
是一个参数,可以在组件中通过useParams
来获取。
现在,你可以打开浏览器,尝试以下链接,看看效果:
http://localhost:5173/
http://localhost:5173/hello
http://localhost:5173/hello/123
http://localhost:5173/hello/abc/a
这些路径都会展示我们的 HelloWorld
页面。
路径参数
在刚刚的内容中,我们给出了 path="/hello/:id"
这样的路由,这种路由可以接受一个参数,这个参数可以在组件中通过 useParams
来获取。现在,比方说我们希望用 id
来表示页面上展示的提示条序号,比如说访问 id
为 1
的页面,我们展示 提示条 #1
,访问 id
为 2
的页面,我们展示 提示条 #2
,以此类推。让我们来实现这个功能。
首先,进入 HelloWorld.tsx
文件,就和其他的函数一样,在页面中,在返回之前,我们也可以进行其他操作。现在,让我们在 return
前,添加 const { id } = useParams();
,这样我们就可以通过 id
来获取到路径参数了。注意,useParams
是一个 React Router
提供的 hook
(钩子,一种特别的函数),我们需要先引入它,所以在文件的开头,我们需要添加 import { useParams } from "react-router-dom";
。
之后,我们就可以使用 { id }
来获取到路径参数 id
了,接下来,我们可以根据 id
来展示不同的提示条。让我们来看看完整的代码:
现在,你可以尝试访问 http://localhost:5173/hello/2
,你应该可以看到:
提示条 #2
这是一个内容
模板框架
让我们观察一下常见的网站,比如说你现在看到的这个教程页面。其实你会发现,无论你在看教程的哪个部分,大体的布局是不变的,只有内容是变化的。这就是一个模板框架的概念,在这个部分,我们会尝试着实现一个简单的模板框架。就像这样:
测试页面
页面 1
测试页面
页面 2
测试页面
页面 3
我们假设我们有三个页面,我们希望能够实现这三个页面都能有一个阴影效果作为页面的背景,并给每个页面都添加一个 “测试页面” 的标题。让我们来实现这个功能!
通过路由实现(推荐)
首先,让我们在 pages
文件夹下新建一个 Template.tsx
文件,用于存放我们的模板框架。在这个文件中,我们可以写入以下代码:
相信你已经可以看懂除了 Outlet
之外的代码了,Outlet
是 React Router
提供的一个组件,用于展示子路由的内容。稍后你就会体会到它的作用。
然后,我们要创建三个页面用于展示我们的模板框架,我们可以在 pages
文件夹下新建一个文件夹 temp
,然后在这个文件夹中新建三个文件 Page1.tsx
、Page2.tsx
和 Page3.tsx
。在这三个文件中,我们直接使用之前介绍的 rafce
快捷键快速生成页面即可。
接下来,打开 main.tsx
文件,我们希望创建一个新的 temp/
路由,并且在这个路由下展示我们的三个页面。让我们在 <Route path="/hello/:id" element={<HelloWorld />} />
下方添加以下代码:
在这里,我们用一个 Route
包裹了另外三个 Route
,这样我们就可以在 /temp/
下展示我们的三个页面了。其中,我们重复利用 Page1
页面,让它即可以作为默认页面,也可以作为 1
页面。
现在,当你访问 http://localhost:5173/temp/
或者 http://localhost:5173/temp/1
时,你应该可以看到:
测试页面
Page1
当你访问 http://localhost:5173/temp/2
时,你应该可以看到:
测试页面
Page2
当你访问 http://localhost:5173/temp/3
时,你应该可以看到:
测试页面
Page3
这样,我们就实现了一个简单的模板框架。
通过组件实现
除此之外,你还可以通过组件的方式来实现模板框架。相比之下,这种方法在每个页面都需要单独调用,没有路由方便。但是,最好还是了解一下这种方法。现在,在 components
文件夹下新建一个 TemplateComponent.tsx
文件,用于存放我们的模板框架。在这个文件中,我们可以写入以下代码:
观察这个文件。由于只有一个 children
参数,我们直接用 :
来定义参数类型,而不是之前的 interface
。这是一种简化的写法,你可以根据自己的喜好来选择,如果你还是希望使用 interface
,你可以这样写:
可以看到,JSX
元素是一种特殊的类型,它表示一个 React
元素。并且 children
是一个特殊的属性,它表示组件的子元素。这是什么意思呢?通常来说,你可能认为给 children
传递参数应该使用:
这样固然没错,但是 React
提供了一种更简便的写法,你可以直接在组件标签中写入子元素,就像这样:
这就是 children
独有的写法。然后,我们就可以用 {props.children}
来获取到子元素了。
现在让我们回到 HelloWorld.tsx
文件,我们可以添加 TemplateComponen
组件,来实现模板框架。现在,我希望你能把之前写的内容包裹进 TemplateComponent
组件中,尝试自己完成吧!这是你需要实现的效果:
测试页面
提示条 #{id}
这是一个内容
Hello world!
这是我的写法:
跳转页面
在传统的 HTML 网站中,我们会使用 <a href="...">
标签来实现页面跳转。但是在 React
中,我们不推荐这样做。因为这样会导致页面刷新和页面的状态丢失,而且会影响用户体验。在 React
中,我们推荐使用 useNavigate
函数来实现页面跳转。比如说,我们希望在点击一个按钮时跳转到 /temp/1
页面,我们可以这样写:
在这里,我们首先引入了 useNavigate
函数,然后把他赋值给 navigate
变量。之后,我们在按钮的 onClick
事件中(当用户点击时)调用 navigate
函数,并传入我们希望跳转的路径。这样,我们就可以实现页面的跳转了。
现在,轮到你来实现了!在 HelloWorld.tsx
文件中,添加一个按钮,当用户点击时,跳转到 /temp/1
页面。这是我的答案:
现在,你可以尝试点击按钮,看看效果!
总结
路由的内容比较多,并且路由这个概念对你来说可能也比较陌生。如果你对部分内容不确定,可以多看几遍,始终记得你可以在 前端课程 GitHub 中找到对应的代码。