import {BrowserRouter as Router, Link, Route, Switch} from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Router>
</Router>
3. Route组件
route组件是路由的映射组件,通过该组件将url地址和React组件进行映射,映射后当url地址变为指定地址时指定的组件就会显示,否则不显示。
<Route path="/home" component={Home} />
<Route path="/about" component={About} />
上例中,路径/home
和<Home/>
组件进行了映射,路径/about
和<About/>
组件进行了映射。当访问http://localhost:3000/about
时,about组件会自动渲染显示,访问http://localhost:3000/home
时,home组件会自动渲染显示。
Route组件可以设置以下几个属性
- path
- exact
- strict
- component
- render
- children
- location
- sensitive
用来设置要映射的路径,可以是一个字符串或字符串数组。字符串用来匹配单个路径,数组可以匹配多个路径。看一个数组的例子:
<Route path={["/about", "/hello"]}>
<About/>
</Route>
使用数组映射后,当我们访问数组中的路径时都会使组件挂载。设置路径时也可以在路径中设置参数,比如:/student/:id
其中id就是一个参数,可以动态的传递:id
的值,换句话说/student/1
或/student/2
,都会触发组件挂载。
设置动态参数后,在组件的内部可以使用useParams()
钩子来读取参数:
const Student = () => {
const {id} = useParams();
return <div>学生id:{id}</div>
...略...
<Route path="/student/:id">
<Student/>
</Route>
...略...
exact
路由的匹配默认并不是完整匹配,这意味着路由映射的地址是/home
时,只要我们访问的路径是以/home
开头就会触发组件的挂载,默认情况下是不会检查路由的子路径的。比如:/home/hello
、/home/abc
等都会导致home组件挂载。
exact属性用来设置路由地址是否完整匹配,它需要一个布尔值,默认为false,就像上边的情况。如果设置为true,那么只有地址和path完全一致时,组件才会挂载。
<Route path="/home" exact>
<Home/>
</Route>
这样一来只有访问/home
时,home组件才会挂载,差一个字母都不行哦!
strict
布尔值,默认值为false。false时,会匹配到以/
结尾的路径。比如:path设置为/home
默认情况下/home/
也会导致组件挂载。设置为true时,以/
结尾的路径不会被匹配。
component
设置路径匹配后需要挂载的组件。作用和Route的标签体类似。
<Route path="/home" component={Home}/>
和标签体指定组件不同,如果通过component属性指定组件,React Router会自动向组件中传递三个参数match、location和history。
match
对象,表示请求匹配的路径信息,其中包含四个属性:
- param —— 请求参数
- isExact —— 布尔值,请求路径是否完整匹配
- path —— 请求路径的规则
- url —— 匹配到的url地址
location
对象,表示浏览器地址栏的信息,请求完整路径、查询字符串等,可能具有的属性:
- pathname —— 请求的路径
- search —— 查询字符串
- hash —— hash字符串
- state —— 历史记录中的状态对象,可以用来在跳转时传递数据
history
对象,用来读取和操作浏览器的历史记录(页面跳转)等功能,属性:
- length —— 历史记录的数量
- action —— 当前历史记录的状态,pop(前进、后退、新记录创建、索引发生变化);push(新记录添加);replace(历史记录被替换)
- location —— location对象
- push() —— 添加新的历史记录
- replace() —— 替换历史记录
- go() —— 跳转到指定记录
- goBack() —— 回退
- goForward() —— 前进
- block() —— 用来阻止用户跳转行为,可以用Prompt组件代替
render
render也是Route组件中的属性,和component类似,也用来指定路径匹配后需要挂载的组件。只是render需要的是一个回调函数作为参数,组件挂载时,render对应的回调函数会被调用,且函数的返回值会成为被挂载的组件。render的回调函数中会接收到一个对象作为参数,对象中包含三个属性,即match、location和history,我们可以根据需要选择是否将其传递给组件。
<Route path="/student/:id" render={routeProps => <Student {...routeProps}/>} />
children
children实际上就是组件的组件体,设置方式有两种一个是通过组件体设置,一个是通过children属性设置。它的值也有两种方式,一种直接传递组件,这样当路径匹配时组件会自动挂载。一种是传递一个回调函数,这样它和render的特点是一样的。
直接设置组件:
<Route path="/student/:id" children={<Student/>} />
<Route path="/student/:id">
<Student/>
</Route>
传递回调函数:
<Route path="/student/:id" children={routeProps => <Student {...routeProps}/>} />
<Route path="/student/:id">
{routeProps => <Student {...routeProps}/>}
</Route>
需要注意的时,当children接收到的是一个回调函数时,即使路径没有匹配组件也会被挂载到页面中(没有使用Switch标签的情况下),这一特性可以在一些特殊应用场景下发挥作用。如果不希望出现路径不匹配时组件被挂载的情况,最好选择使用render来代替。
4. Switch组件
Switch组件是Route组件的外部容器,可以将Route组件放入到Switch组件中。放入Switch组件中后,匹配路径时会自动自上向下对Route进行匹配,如果匹配到则挂载组件,并且一个Switch中只会有一个Route被挂载。如果将Route组件单独使用,那么所有的路径匹配的Route中的组件都会被挂载。
5. Link组件
Link组件作用类似于a标签(超链接),并且Link组件在浏览器中也会被渲染为超链接。但是Link组件生成的链接点击后只会修改浏览器地址栏的url,并不会真的向服务器发送请求。这种方式有利于组件的渲染,所以在开发中应该使用Link组件而不是超链接。
1. HashRouter组件
除了BrowserRouter以外,react router中还为我们提供了HashRouter,它是干什么用的呢?其实很简单,当我们使用BrowserRouter时,路径会直接根据url地址进行跳转,也就是我们在使用应用时在浏览器的地址栏看到的地址就和我们正常去访问网页一样。
但是,HashRouter不是这样,使用HashRouter时,组件的跳转不再是以完整的url形式,而是通过url地址中的hash值进行跳转(url地址中#后的内容为hash值)。
BrowserRouter的地址栏
import React from ‘react’;
import ReactDOM from ‘react-dom/client’;
import { BrowserRouter as Router, Link, Route, Routes } from ‘react-router-dom’;
const Home = ()=>{
return <div>首页</div>
const About = () => {
return <div>关于</div>
const App = () => {
return <div>App
<Link to=”/”>home</Link>
<Link to=”/about”>about</Link>
<Routes>
<Route path=”/” element={<Home/>}/>
<Route path=”/about” element={<About/>}/>
</Routes>
</div>;
const root = ReactDOM.createRoot(document.getElementById(‘root’));
root.render(
<Router>
<App />
</Router>
Routes组件
和版本5不同,6中的Route组件不能单独使用,而是必须要放到Routes组件中。简言之Routes就是一个存放Route的容器。
Route组件
Route作用和版本5的一样,只是变得更简单了,没有了那么多复杂的属性,并且Route组件必须放到Routes中,当浏览器的地址发生变化时,会自动对Routes中的所有Route进行匹配,匹配到的则显示,其余Route则不再继续匹配。可以将Route当成是一个类似于if语句的东西,路径(path)匹配则其中的组件便会被渲染。
- path —— 要匹配的路径
- element —— 路径匹配后挂载的组件,直接传JSX
- index —— 布尔值,路由是否作为默认组件显示
Outlet组件
Outlet组件用来在父级路由中挂载子路由。
在版本6中Route组件是可以嵌套的,可以通过嵌套Route来构建出嵌套路由,像这样:
<Route path='/students' element={<StudentList/>}>
<Route path=':id' element={<Student/>}/>
</Route>
上例中,Route嵌套后,如果访问/students
则会挂载StudentList组件,如果访问/students/:id
则会自动在StudentList组件中对Student组件进行挂载。在StudentList组件中就可以使用Outlet来引用这些被挂载的组件。
const StudentList = () => {
return <div>
<Outlet/>
Link组件
和版本5的类似,具体区别看视频
NavLink组件
和版本5的类似,具体区别看视频
Navigate
类似于版本5中的Redirect组件,用来跳转页面,具体看视频
部分钩子函数
- useLocation —— 获取地址信息的钩子
- useNavigate —— 获取Navigate对象的钩子
- useParams —— 获取请求参数
- useMatch —— 检查路径是否匹配某个路由
超哥,useNavigate和Navigate都可以实现页面跳转,所以区别就是useNavigate可以用函数进行操作,Navigate组件是默认渲染时就被挂载。可以这么理解吧。
感谢社会我超高,超高的课讲得很火爆。麻烦问超哥一个问题:
<Routes>
<Route className=’display’ path=’/robbin/home’ element={<Home />}/>
<Route className=’display’path=’/robbin/about’ element={<About />}/>
<Route className=’display’path=’/robbin/source’ element={<Source />}/>
</Routes>
<Routes>
<Route className=’homebranch’ path=’/robbin/home/news’ element={<News />}/>
<Route className=’homebranch’ path=’/robbin/home/message’ element={<Message />}/>
</Routes>
上面是嵌套路由,结果得到一下错误提示。
You rendered descendant <Routes> (or called useRoutes()
) at “/robbin/home” (under <Route path=”/robbin/home”>) but the parent route path has no trailing “*”. This means if you navigate deeper, the parent won’t match anymore and therefore the child routes will never render.
Please change the parent <Route path=”/robbin/home”> to <Route path=”/robbin/home/*”>
按照错误提示做相应修改后(在home后的路径后加 /*),不再有错误提示,但子路由组件仍然不挂载。没有错误提示,也不挂载组件,这可咋整?