3 NavLink简单封装
在之前使用NavLink标签时,只有2个,代码如下:
<NavLink activeClassName="g2zh" className='list-group-item' to="/about">About</NavLink>
<NavLink activeClassName="g2zh" className='list-group-item' to="/home">Home</NavLink>
试想一想,如果我们路由链接有十几个或者更多时,如果还上这样写代码就有很多冗余,即activeName和className
有大量重复,这时我们可以考虑对NavLink简单封装,封装为一个一般组件。
一般组件MyNavLink初始代码3-2如下:
import React, { Component } from 'react'
import { NavLink } from "react-router-dom";
export default class MyNavLink extends Component {
render() {
return (
<NavLink activeClassName="g2zh" className='list-group-item' to="/about">About</NavLink>
)
}
}
其中to为组件的属性,我们可以通过props来动态接收,那么About这个标签体内容我们如何动态接收呢?
在react组件中,标签体是一种特殊的props,key被指定为children,value为标签体的值。
对上述MyNavLink组件做动态修改如下:
<NavLink activeClassName="g2zh" className="list-group-item" {...this.props} />
相应的App.jsx路由组件改为我们自定义的一般组件,代码如下:
<MyNavLink to="/about">About</MyNavLink>
<MyNavLink to="/home">Home</MyNavLink>
如果我们想写闭合标签的形式,怎么做呢?即写成<MyNavLink />的形式,前面我们提到标签体也是一种prop,然后key为指定的children,修改如下:
<MyNavLink to="/about" children="About" />
<MyNavLink to="/home" children="Home" />
总结
- NavLink可以实现路由链接的高亮,通过activeName指定样式;
- 标签体内容是一个特殊的标签属性;
- 通过
this.props.children
可以获取标签体内容。
4 switch的使用
我们在定义一个Test路由组件,代码4-1如下所示:
import React, { Component } from 'react'
export default class Test extends Component {
render() {
return (
<h3>我是test的内容</h3>
)
}
}
APP.jsx代码4-2如下所示,其他同上:
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Test} />
页面效果图4-1如下所示:
正常我们一个路由链接对应一个路由组件,现在我们点击Home链接,因为path属性相同,都匹配且展示。
react做路由匹配默认从头匹配到结束,只要path值对应,都能匹配,这样不符合我们预期,且效率很慢。这时候,需要用到switch
Switch
是 React Router 提供的一个组件,它用于将路由包装在一起,只渲染第一个匹配的路由。也就是说,如果一个 URL 匹配了多个路由,Switch
只会渲染第一个匹配的路由,忽略其他的路由。
我们修改App.jsx代码4-3如下所示:
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Route path="/home" component={Test} />
</Switch>
5 解决样式丢失问题
有这么一个需求,我们希望我们的路径前面同一加上公司标志或者团队标志。那么我们现在修改路由链接和路由组件,如下所示:
<div className="list-group">
{/* react中靠路由链接实现组件切换--编写路由链接 */}
<MyNavLink to="/g2zh/about">About</MyNavLink>
<MyNavLink to="/g2zh/home">Home</MyNavLink>
</div>
{/*省略其他 */}
<div className="panel-body">
{/* 注册路由 */}
<Switch>
<Route path="/g2zh/about" component={About} />
<Route path="/g2zh/home" component={Home} />
</Switch>
</div>
当前项目启动后,点击路由链接切换等,样式都正常。但是当我们刷新页面的时候,样式丢失了,动态演示图5-1如下所示:
- 知识点:
我们的脚手架项目webpack配置内置devServer服务器,默认根路径为public。当 React 前端应用找不到请求的资源时,通常会返回 index.html 文件,这是因为 React 的应用通常是一个单页应用(SPA),只有一个 HTML 文件,所有的路由和组件都是在该 HTML 文件中动态加载的。
我们的样式通过bootstrap.css实现的
-
初始启动,浏览器地址:http://localhost:3000,默认加载publick下index.html.
-
Index.html通过
<link rel="stylesheet" href="./css/bootstrap.css">
加载样式,我们查看下网络请求 :- 通过相对路径可以正常请求到样式,页面正常。
-
当我们刷新时,我们在观察下网络请求样式:
- 根据相对路径,请求路径为Request URL: http://localhost:3000/g2zh/css/bootstrap.css,该路径下资源不存在,返回了首页。样式加载失败,页面表现就是样式丢失。
-
造成样式丢失原因:多级路径下,刷新页面;样式通过非’/‘开头的相对路径引入,导致样式加载失败。
-
解决方案:
-
方式一:我们首页引入样式通过非’/‘相对路径引入样式,那么我们就把引入样式的方式通过’/‘开头引入样式,即固定去跟路径下寻找资源,不会造成样式丢下。
-
首页样式样式代码修改如下```
<link rel="stylesheet" href="/css/bootstrap.css">
-
-
方式二:通过绝对路径形式,我们的静态资源一般放在public某个路径下,%PUBLIC_URL%在react脚手架中表示public文件夹的绝对路径。
-
首页样式引入修改如下
<link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css">
-
-
方式三(不推荐):把BrowserRouter替换为HashRouter,hash模式刷新的时候#后面会忽略。
- 作为参考,美团前端使用react,属性页面属性并不会丢失,同时页面路由使用BrowserRouter。
-
6 路由的模糊匹配和严格匹配
React 路由提供了两种匹配方式:模糊匹配(默认)和严格匹配。它们之间的区别在于,模糊匹配会忽略 URL 中的多余部分,而严格匹配则要求 URL 必须完全匹配。
默认情况下,React 路由采用模糊匹配方式,这意味着如果当前 URL 的开头部分与某个路由规则相匹配,就会将其视为匹配成功,无论后面是否还有其他路径。
例如,如果路由规则如下:
<Route path="/about" component={About} />
那么,以下 URL 都会被视为匹配成功:
/about
/about/
/about/something-else
这是因为模糊匹配会忽略 URL 的多余部分,只关注开头部分是否匹配。
如果想要采用严格匹配方式,需要将 <Route>
组件的 exact
属性设置为 true
,如下所示:
<Route exact path="/about" component={About} />
这样,只有当 URL 完全匹配 /about
时,才会视为匹配成功。因此,以下 URL 都不会被视为匹配成功:
/about/
/about/something-else
需要注意的是,严格匹配通常适用于只有一个路由规则的情况,如果有多个路由规则,可能会导致一些问题。例如,如果有以下两个路由规则:
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
那么,当访问 /about
时,由于第一个路由规则采用了严格匹配,因此不会匹配成功,从而导致渲染结果出现错误。因此,在使用严格匹配时,需要仔细考虑每个路由规则的具体情况,以免出现问题。
总结:
- 默认使用模糊匹配,即输入的路径匹配起始路由规则;
- 开启严格匹配模式,添加exact属性,输入路径与批评规则严格一致;
- 严格模式需要在开启,可能导致无法匹配二级路由。
7 Redirect
<Redirect>
组件是 React Router 提供的一种路由重定向的方式。它可以将用户重定向到另一个 URL,用于在用户访问某些页面时进行身份验证或其他控制流程。
<Redirect>
组件通常用在路由渲染函数中,当路由匹配成功时,返回一个 <Redirect>
组件,该组件会自动将用户重定向到指定的 URL
应用场景:我们前面的测试案例,默认启动展示区不展示任何东西,但是正常应用,比如后台管理未登陆情况下会重定向至登陆页,在登陆后会默认显示dashboard等等。
改造我们的测试示例,App.jsx代码7-1如下所示:
{/* 注册路由 */}
<Switch>
<Route path="/about" component={About} />
<Route path="/home" component={Home} />
<Redirect to="/about"></Redirect>
</Switch>
效果就是启动之后,我们的‘/‘路径在匹配不上其他的路由时,重定向’/about’,即展示区显示About组件的内容。
总结:
- 一般写在所有路由注册的最下方,当所有路由都无法匹配时,重定到Redirect指向的路由。
结语
❓QQ:806797785
⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git
参考:
[1]React视频教程[CP/OL].2020-12-15.p79-84.
[2]React官网[CP/OL].
[3]ChatGPT[CP/OL].