文章目录
1、介绍
现代的前端应用大多数是SPA(单页应用程序),也就是只有一个HTML页面的应用程序。因为它的用户体验更好、对服务器压力更小,所以更受欢迎。为了有效的使用单个页面来管理多页面的功能,前端路由应运而生。
- 前端路由功能:让用户从一个视图(组件)导航到另一个视图(组件)
- 前端路由是一套映射规则,在React中,是URL路径与组件的对应关系
- 使用React路由简单来说,就是配置路径和组件
2、路由使用
https://reactrouter.com/
2.1、相关组件
- Router组件:包裹整个应用,一个React应用只需要使用一次
Router: HashRouter和BrowserRouterHashRouter
: 使用URL的哈希值实现 (localhost:3000/#/first)BrowserRouter
:使用H5的history API实现(localhost3000/first)
- Link/NavLink组件:用于指定导航链接(a标签)
最终Link会编译成a标签,而to属性会被编译成 a标签的href属性 - Route组件:指定路由展示组件相关信息(组件渲染)
path
属性:路由规则,这里需要跟Link组件里面to属性的值一致
-component
属性:展示的组件
各组件关系示意图
2.2、安装路由模块
路由模块不是react自带模块,需要安装第3方模块
npm i -S react-router-dom@5
定义项目使用路由,在入口文件/src/index.js文件中定义路由模式
定义路由规则和匹配成功的渲染组件
在浏览器中输入后尝试匹配
3、声明式导航
使用Link或NavLink组件完成声明式导航的定义
Link组件
Link组件不会根据路由的变化而添加或修改编译后html标签中的属性
NavLink组件
NavLink会根据路由的变化而自动修改编译后html标签中的属性
如果当前的路由规则和Navlink中的To所写的规则一致,则添加class样式,默认名称为 active,可以通过activeClassName来修改匹配成功后样式名称。
exact
exact是Route下的一个属性,react路由会匹配到所有能匹配到的路由组件,exact能够使得路由的匹配更严格一些。
访问/about时候,/也会匹配到,也会显示/对应组件,就是home组件,就显示了home的内容,这样就不对了,加上exact,就正常了
4、编程式导航
react-router-dom中通过history对象中的push/replace/goBack
等方法实现编程式导航功能。
编程式导航
在react-router-dom中,
只要是路由规则匹配成功后,直接渲染的组件中,它的this.props中都会有3个路由对象
this.props.history 此对应就是用来完成编程式导航所用 push/replace/goBack
this.props.match 获取路由对象中的数据
this.props.location 获取路由对象中的数据
跳转
5、页面路由数据传递
路由参数:在Route定义渲染组件时给定动态绑定的参数。
React路由传参方式有三种:
1. 动态路由参数(param)
以“/detail/:id”形式传递的数据
在落地组件中通过this.props.match.params得到
2. 查询字符串(search)
通过地址栏中的 ?key=value&key=value传递
在落地组件中通过this.props.location.search得到
3. 隐式传参(state),通过地址栏是观察不到的
通过路由对象中的state属性进行数据传递
在落地组件中通过this.props.location.state得到
6、嵌套路由
在有一些功能中,往往请求地址的前缀是相同的,不同的只是后面一部份,此时就可以使用多级路由(路由嵌套)来实现此路由的定义实现。
例如,路由规则如下
admin/index
admin/user
它们路由前缀的admin是相同的,不同的只是后面一部份。
实现方式
先需要定义个组件,用于负责匹配同一前缀的路由,将匹配到的路由指向到具体的模块
<Route path="/admin" component={Admin}></Route>
// 创建模块路由组件负责指定各个路由的去向
render() {
// 获取前缀,供后续地址做路由拼接
let prefix = this.props.match.path;
return (
<div>
<h1>欢迎使用后台管理程序</h1>
<Route path={`${prefix}/user`} component={User}></Route>
<Route path={`${prefix}/goods`} component={Goods}></Route>
</div>
);
}
重定向 404 路由参数类型限制 可选参数
7、路由渲染方式
7.1、component (组件对象或函数)
<Route path="/home" component={Home} />
或
<Route path="/home" component={(router)=><Home {…router} />} />
类静态
它渲染的组件通过this.props
能够得到路由对象
如果Route所在的组件中有数据更改,则它对应匹配的组件不进行创建,无操作
回调函数
性能不是太好,一般不建议去使用
它渲染的组件通过this.props无法得到路由对象,需要手动向下传递
如果Route所在的组件中有数据更改,则它对应匹配的路由组件则进行创建新的
因为它是回调函数的方式,所以它可以在匹配对应渲染的组件时,可以先进行逻辑判断 --模拟路由独享守卫
7.2、render (函数)
用它来一般完成路由独享守卫,它有component类渲染方式的优点也有component回调函数方式的优点
<Route path="/home" render={router=><Home {…router} />} />
7.3、children (函数或组件)
在组件渲染显示时,不是关注与它是否显示,而是在显示的时候关注于它的路由相关信息,才用到它
1.组件方法 精确匹配,地址栏中的规则和path路由一致它才匹配组件渲染,缺点:this.props中的路由对丢失
// 精确匹配
<Route path="/about" children={<About />} />
2.回调函数
全匹配,它不关心地址栏中的地址是否于当前path属性规则一致,它都渲染对应的组件,只不过在回调函数的router参数中,有一个match属性,如果地址栏中的地址和当前path路径一致,则match属性为对象,否为null,一般用children回调函数的方案
作用:视图中显示根据地址栏或路由中的某些字段来动态显示,我们可以用children回调函数方式.
// 全匹配
<Route path="/about" children={router =>{
return <div>children渲染</div>
}} />
用它来做404
8、withRouter高阶组件
作用:把不是通过路由直接渲染出来的组件,将react-router
的 history、location、match
三个对象传入props对象上
默认情况下必须是经过路由匹配渲染的组件才存在this.props
,才拥有路由参数,才能使用编程式导航的写法,执行this.props.history.push('/uri')
跳转到对应路由的页面,然而不是所有组件都直接与路由相连的,当这些组件需要路由参数时,使用withRouter
就可以给此组件传入路由参数,此时就可以使用this.props
// 引入withRouter
import { withRouter} from 'react-router-dom'
// 执行一下withRouter
export default withRouter(Cmp)
或者
@withRouter
例子1:App组件不是通过路由直接渲染出来的组件
例子2:点击按钮跳转页面
所以withRouter的作用就是, 如果我们某个东西不是一个Router, 但是我们要依靠它去跳转一个页面, 比如点击页面的button, 返回Home页, 这时候就可以使用withRouter来做.
上面使用装饰器的写法,下面换种写法
例子3:需要先登录才能访问user页面
模拟全局导航守卫
9、自定义导航组件
为何需要自定义导航?
因为在项目中往往不是所有的声明式导航都是需要a标签完成,有时候可能需要别的标签,此时如果在需要的地方去写编程式导航就会有代码重复可能性,就在对于公共代码进行提取。
思路:
- 定义一个普通组件可以是类组件也可以是函数式组件
- 父组件能向子组件传值 props ,限制数据类型
- 此高阶组件不管路由规则是否匹配都要有渲染 children
需求:
当前url=user
给页面中的跳转到user的导航加上active
chiledren回调函数形式:如果地址栏中的地址和当前path路径一致,则match属性为对象,否为null,
参考: