路由 简介
根据不同的url,来切换对应的组件。
实现spa(单页面应用)应用:整个项目只有一个完整页面,页面切换不会刷新页面(不会感觉页面的闪烁,更加贴近原声应用的体验)。
当前版本 V5
(二)路由—分类
-
React-Router:提供了一些router的核心API,包括Router, Route, Switch等,但是它没有提供 DOM 操作进行跳转的API。
-
React-Router-DOM:提供了 BrowserRouter, Route, Link等 API,我们可以通过 DOM 的事件控制路由。例如点击一个按钮进行跳转,大多数情况下我们是这种情况,所以在开发过程中,我们更多是使用React-Router-DOM。
(三)路由模式— HashRouter 和 BrowserRouter
-
HashRouter (hash模式)
url中会有个#
,例如 localhost:3000/#,HashRouter就会出现这种情况,它是通过hash值来对路由进行控制。如果你使用HashRouter,你的路由就会默认有这个#。刷新不会丢失。 -
BrowserRouter(历史记录模式 )
是通过历史记录api来进行路由的切换的很多情况下我们则不是这种情况,我们不需要这个#,因为它看起来很怪,这时我们就需要用到BrowserRouter。刷新会丢失404(上线中会出现问题 本地开发中不会)
(四)路由— link 与 switch
-
Link :主要API是
to
,to可以接受string或者一个object,来控制url。 -
NavLink :它可以为当前选中的路由设置类名、样式以及回调函数等。
to
属性跳转路径,activeClassName
是当元素处于活动状态时应用于元素的样式。
路由 使用 相关
(一)路由基本使用
路由最基本的职责就是:当页面的访问地址与 Route 上的 path 匹配时,渲染出对应的 UI 界面。
1、下载路由模块
npm install --save react-router-dom
2、在index.js引用路由模块
import { BrowserRouter} from 'react-router-dom';
3、在index.js使用路由模式包裹根组件
4、在app.js中引用路由出口
import {Route} from "react-router-dom"
5、配置
<Route path="/路径" component={组件}/>
(二)路由模式— hash模式
要切换hash模式,只需要在 index.js设置路由模式即可。
(三)路由导航 — Link
使用Link组件即可, to属性就是地址。
(四)路由导航 — NavLink
导入NavLink:
如果不喜欢默认的类名active ,可以手动设置选中Class,方便样式设置。
如果不想全部修改class名,可以单个修改:
注意:如果在vscode的终端中启动项目可能会无效 在外部cmd中启动。
(五)exact 属性 精确匹配
exact表示当前路由path的路径采用精确匹配。比如说Home的path如果不加上exact,那么path="/about"将会匹配about他自己与path="/“这两个,所以一般path=”/"这个路由会加上exact。
另外需要注意一点的是嵌套路由不要加exact属性,如果父级路由加上,这里例如topics加上该属性,他下面的子路由将不会生效,因为外层强制匹配了。
不过一般我们也不会直接通过"/"跳转,会通过路由重定向到某个页面。
(六)路由–404页面
有的时候用户可能会错误修改相关url ,但是并没有相关路由 ,解决方式设置404路由组件。
404页面需要写在路由最底部,然后不需要设置path。
但是有一个问题,不管到那个页面都会有这个404路由组件。
可以设置router唯一渲染,把404页面路由放在最下面,这样的话,上面如果匹配到相关路由,就只渲染那一个路由页面;如果什么都匹配不到了,才会加载404页面。
(七) < Switch >
解决route的唯一渲染的问题,保证路由只渲染一个路径。
<Switch>
是唯一的,因为它仅仅只会渲染一个路径,当它匹配完一个路径后,就会停止渲染了。
只会匹配一个:
但是发现,在初始化的时候还是会出现404组件。
因为没有路由重定向,在初始化时会去找"/"的路由页面,发现没有的话,就会跳到404页面。
(八)路由—重定向
导入Redirect:
import { BrowserRouter,Route,Link,NavLink,Redirect } from 'react-router-dom'
定义重定向路径:
<Redirect from="/" to="/demoa" exact/>
exact精确匹配一定要加,不然,每次路由跳转都会匹配一次"/"。
二级路由
1、在子页面中引用路由模块:
import {Route,Link} from 'react-router-dom'
2、设置相关规则 与 路由导航。
路由 跳转 传参
(一)路由 — js跳转
1、push方法在路由页面中跳转:
this.props.history.push("/xxxx")
如果有报错,通过withRouter组件来解决。为什么会报错,因为不是路由跳转的页面,没有location match history这三个属性,既然没有history这个属性,我们当然用不了this.props.history.push()。
解决方式:引用withRouter组件
修改导航组件,删除组件的暴露
在最底部用高阶组件重新暴露组件
(二)withRouter
withRouter作用是:让非路由切换的组件也具有路由切换的功能,也具有组件的三个属性(location match history)。
(三)其他跳转方式
replace() 替换当前路径
goBack() 后退
goForward() 前进
(四)params 传参
1、在 Router标签后面拼接传递参数的名字:
2、设置发送的数据:
3、在需要接受的路由组建中接受this.props.match.params.name
:
--------params路由传参方式的优缺点----------------
优势 : 刷新地址栏,参数依然存在。
缺点 : 只能传字符串,并且,如果传的值太多的话,url会变得长而丑陋。
(五)state 传参
1、在Link中设置发送的数据:
<Link to={{ pathname : '/d' , state: { name : 'sunny' }}}>点我去d</Link>
2、在需要接受的路由组件中接收:
console.log(this.props.location. state.name)
--------state路由传参方式的优缺点-----------------
优势:浏览器地址栏不显示传递的数据,传递参数可传对象。
缺点:刷新地址栏,参数丢失。
路由render渲染写法
(一)render渲染写法
修改Route 里面的组件调用方式为:
render={(props)=>{return <组件/>}}
而且还可以通过逻辑判断,来调用不同的组件,比如三元运算,这就是简单的路由验证:
render={(props)=>{return false?<组件1/>:<组件2/>}}
render调用一个函数,那么我们就可以决定什么条件下渲染他。如果同时传入props,那么就可以在路由组件中使用history: {…}
, location: {…}
, match: {…}
这几个对象。
友友文章:react-router4渲染组件的方式
(二)路由render渲染写法 传递数据
只需要向组件内部传递即可 ,正向传值:
取值:
不过我们一般不在路由里面向组件传值。
路由验证
如果想对路由进行验证的话,只需要在函数中进行逻辑编写,可以设置具体渲染哪个组件。
路由钩子函数
使用react生命周期进行验证。
react-router v4,舍弃了onEnter,onUpdate,onLeave,它使用componentDidMount或componentWillMount来代替onEnter,使用componentDidUpdate 或 componentWillUpdate来代替onUpdate,使用componentWillUnmount来代替onLeave。
参考:react 利用路由钩子函数进行设置网页标题以及登录验证
react路由懒加载(异步组件)— react-loadable
1、安装:npm install --save react-loadable
2、创建:在src下自定义目录"/util/loadable.js"
3、在loadable.js中设置过场动画:
import React from 'react';
import Loadable from 'react-loadable';
//通用的过场组件
const loadingComponent =()=>{
return (
<div>loading</div>
)
}
//过场组件默认采用通用的,若传入了loading,则采用传入的过场组件
export default (loader,loading = loadingComponent)=>{
return Loadable({
loader,
loading
});
}
4、修改路由页面的引用方式:
import React, { Component } from 'react'
import { BrowserRouter, Route,Link,NavLink} from 'react-router-dom';
//路由懒加载
import loadable from '../util/loadable' //引入过场动画
const Demob = loadable(()=>import('./Demob')) //路由懒加载
let Democ = loadable(()=>import('./Democ')) //路由懒加载
export default class Demoa extends Component {
render() {
return (
<div>
<BrowserRouter>
<Route path="/b" component={Demob}/>
<Route path="/c" component={Democ}/>
</BrowserRouter>
</div>
)
}
}