1. react-router包的下载
npm install react-router-dom -S
2. 基本使用
2.1 react-router主要的API
- 【HashRouter】与【BrowserRouter】,两个API是两种路由模式,被包裹,意味着当前组件开启了路由
- 【Link】与【NavLink】,两个API用于路径跳转,最终会被渲染成【a】标签,可以通过【to】属性,设置路由跳转路径
- 【Route】用于路径的匹配,被匹配到的路径,就会显示指定的页面
- 【path属性】,用于设置路径匹配
- 【component属性】,路径匹配成功后,要显示的组件。
- 【exact属性】,精准匹配,只有精准哦匹配完整完全一样的路径,才会渲染组件
import {HashRouter,Link,Route} from 'react-router-dom'
import Home from './Home.js'
import List from './List.js'
function App () {
return (
<div>
<HashRouter> 【 开启路由 hash模式 】
<Link to="/" >首页</Link>
<Link to="/list">列表</Link>
<Route path="/" component={Home} exact /> 【 精准的匹配,只有匹配到 / 才能进行展示 】
<Route path="/list" component={List} />
</HashRouter>
</div>
)
}
export default App
function Home() {
return (
<div>Home</div>
)
}
export default Home
function List() {
return (
<div>List</div>
)
}
export default List
3. 路由匹配规则Switch
- 【Switch】组件将Route进行包裹,目的是只有匹配到的路由组件,才被显示,匹配不到的是不显示
- Switch: 如果一个组件上出现多了相同的路由匹配路径,在跳转时,会同时显示,使用switch就可以打断重复的组件被显示
import { Switch,Route } from 'react-router-dom'
<Switch>
<Route path="/home" component={Home} />
<Route path="/list" component={List}/>
<Route path="/list" component={List}/>
</Switch>
- 如果所有的路由都没有被匹配到,就显示默认路由组件
【防止用户在访问组件时,在地址后面,添加其他,但是被匹配的组件就会显示,所以需要展示404组件】
<!--在组件的后面设置exact-->
<Route path="/list" component={List} exact/>
<!--设置的时候,无需设置匹配路径-->
<Route component={ NotDefined } />
4. 路由跳转(原生JS)与重定向
在某一些情况下,当前用户处于未登录的状态,但是他访问了登陆后访问的页面,这时就需要重定向,让用户跳转到登录的页面
4.1 原生
<!-- 方式一:引入包使用,使用方法 -->
import { createHashHistory } from 'history'
<button onClick={ () => {createHashHistory().push('/home')} }>点击跳转首页</button>
<!-- 方式二: 不需要使用引入的包 只有是当前组件是路由组件的时候,才会有history属性 -->
<button onClick={ ()=> {this.props.history.push('/home') } }>点击跳转首页</button>
4.2 react-router-dom [Redirect] API
<!-- 引包 -->
import { Redirect } from 'react-router-dom'
【设置成标签,to属性就是要重新跳转的页面地址】
<Redirect to="/list" />
5. 路由嵌套
也就是当前组件内,有两个按钮,进行跳转,但是不希望去跳转,只是两个组件之间来回切换,而不是路由跳转
举例pc端的网易云音乐,默认展示发现音乐,在发现音乐里面,下面还有【推荐,排行榜,歌单】等等,通过点击每一个,都是展示对应的内容,再点击的时候发现是在发现页面里面尽心展示的,并没有跳转到其他的页面,所以【推荐】以及其他的都是【发现页面】里的二级,不跳转到其他页面,只在发现音乐里面展示对象的内容
【 App组件 】
import React, { PureComponent } from 'react'
import Item from './Item'
import {Switch,Link,Route} from 'react-router-dom'
class App extends PureComponent {
render() {
return (
<div>
<Link to="/item">发现页面</Link>
<Switch>
<Route path="/item" component={Item}/>
</Switch>
</div>
)
}
}
export default App
【 item组件,并且组件内部是有二级组件 】
import React from 'react'
import {Switch,Link,Route} from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import List from './Components/List'
function Item() {
return (
<div>
<Link to="/item">我的</Link>
<Link to="/item/about">--关于--</Link>
<Link to="/item/list">列表</Link>
<Switch>
<Route path="/item" component={Home} exact/>
<Route path="/item/about" component={About}/>
<Route path="/item/list" component={List}/>
</Switch>
</div>
)
}
export default Item
在某些情况,当编写路由的时候,将【一级路由】的【url以及path】不小心改掉了,导致组件内的二级路由不能访问,设置动态的【一级路由】
import React,{Component} from 'react'
class Item extends Component{
render(props) {
console.log(this.props);
return (
<div>
<div>
<Link to={`${this.props.match.url}/inner`}>国内新闻</Link>----
<Link to={`${this.props.match.url}/outer`}>国际新闻</Link>
</div>
<div>
<Route path={`${this.props.match.path}/inner`} component={ inner }></Route>
<Route path={`${this.props.match.path}/outer`} component={ outer }></Route>
</div>
</div>
)
}
}
export default Item
6. 动态路由参数
使用【params】传递参数
【相当于vue的router文件内部配置】
<Route path="/detail/:id" component={ Detail } />
【从相当于某一个组件通过拼接路径方式进行传参】
<Link to="/detail/1">文章标签</Link>
【组件内部获取传递过来的数据 ,通过使用props,因为使用了HashRouter,会生成一个对象】
<div>{ this.props.match.params.id }</div>
使用【query】进行参数传递
<Link to={{ pathname: '/home' ,query: { id:111 }}}>前往首页</Link>
【 组件中获取传递过来的数据 】
this.props.location.query
【查询参数传递参数】
<Link to="/home?type='nihao'">前往首页</Link>
<!--使用qs对数据进行处理,并且通过第二个参数,对分隔符进行处理-->
qs.parse(this.props.location.search,{ignoreQueryPrefix:true})
例如商品详情页的参数传递,如果父组件里面没有使用【link】的方式跳转,携带参数,可以使用【history.push】进行路由跳转并且带参数,这个是当使用了【HashRoute】的时候生成的。
【 home 】
import React,{Component} from 'react'
class App extends Componet{
render() {
return (
<div>
<button onClick={this.goList.bind(this}>跳转到list,并且携带参数</button>
</div>
)
}
goList() {
this.props.history.push('/list/:1') 【 01.方式一 】
this.props.history.push({pathname: '/list/1'}) 【 02.方式二 】
}
}
【 list拿到参数 】
console.log(props.match.params.id)
7. 路由守卫与路由守组件
7.1 基本使用
- 路由守卫的作用,当跳转组件的时候,要去做一些验证,比如说验证【用户是否登录】,如果用户没有登录,就要重新定向到登录界面
- 当某一个路由需要设置路由守卫,就需要将【Route】里面的【component】替换成【render】,通过设置【render】判断是否需要跳转
- 【render】属性,值是一个方法
<Route path="/item/list" render={(props) => { 【 props存放的是路由信息对象 】
if(user) { 【 如果用户登录了,就要跳转 】
return <List {...props} /> 【 要跳转到的组件 】
} else {
return <Redirect to="/home" /> 【 如果没有登录,就要重新定向到首页或者是登录页面 】
}
}}/>
7.2 路由组件
当很多条路由需要配置路由守卫,那么代码就要书写很多,所以将路由配置封装成一个组件,需要设置路由守卫的调用组件,并将参数传递给路由组件
【 路由组件封装 】
import React, { PureComponent } from 'react'
import { Route,Redirect } from 'react-router-dom'
class RouterItem extends PureComponent {
state = {
user:false,
}
render() {
const { component: Component, ...residue } = this.props 【 component,是传递过来的组件,residue是所有路由信息 】
return (
<div>
<Route {...residue} render={props => { 【 residue包含path以及其他参数,依次的传递给Route 】
if(this.state.user) {
return <Component {...props}/>
} else {
return <Redirect to="/item" />
}
}} />
</div>
)
}
}
export default RouterItem
【 被设置的路由组件 】
<RouterItem path="/item/list" component={List}/> 【调用封装好的路由组件,信息正常书写,会以props的形式传递给路由组件进行设置】
8. 路由懒加载
- 【为什么要做懒加载】,使用懒加载,可以优化网站首屏加载的速度
- 【怎么设置懒加载】,通过第三方插件库
【 下载包 】
npm i @loadable/component
【 使用 】
import LoadableComponent from '@loadable/component'
const Home = LoadableComponent(() => import('./components/Home'))
9. 非路由组件的参数传递 (待更新)
- 在某种情况下,有一些组件,是不需要配置路由的,他是可以直接在组件里面进行引入使用的
10. react-router-config[简化路由配置]
- 下载安装包
npm install react-router-config --save
- 使用【react-router-config】
const routes = [
{
patch: "路径",
component: 组件,
exact: true /* 精准匹配 */
},
{
path: '/about',
component: 组件,
routes: [ 【 配置子路由 】
{
path: '/about',
component: 组件,
exact: true /* 精准匹配 */
}
]
}
]
export default routes
【 渲染路由组件 】
import { renderRoutes } from 'react-router-config'
import routes from './routes'
function App() {
return (
<div>
{renderRoutes(routes)} 【 渲染路由组件 】
{renderRoutes( props.route.routes )} 【 嵌套路由的渲染 】
</div>
)
}
export default App
10.1 其他的路由知识点
- 路由配置重定向的配置
import React from 'react';
import { Redirect } from "react-router-dom";
const routes = [
{
path: "/",
exact: true,
render: () => ( 【 使用render函数重新渲染重定向组件 】
<Redirect to="/discover"/>
)
},
{
path: "/discover",
component: HYDiscover,
}
]