react路由的基本使用
1. 安装react-router-dom
npm install react-router-dom --save
在入口文件index.js中引入HasRouter组件,并将要使用的到路由的组件进行包裹
import {Link, Route} from 'react-router-dom'
在子组件中引入Link,Route
Link用来配置路由的跳转路径
- to属性设置跳转的路由地址
Route用来设置展示的组件
- component用于设置匹配的路径展示的组件
- path设置匹配的路径
- exact 属性用于让Router中的path与Link中的to完全匹配
Switch标签的作用是将包裹在其中的Router中path重复的进行剔除,只留下唯一的Router
- 包裹的必须直接是route标签的元素
// app.js
import Nav from './components/Nav'
import Home from './components/Home'
import {Link, Route} from 'react-router-dom'
function App() {
return (
<div>
根组件
<div>
<p><Link to='/home'>home</Link></p>
<p><Link to='/nav'>nav</Link></p>
</div>
<div>
<p><Route exact component={Home} path='/home'></Route></p>
<p><Route exact component={Nav} path='/nav'></Route></p>
</div>
<hr />
<div>
<Switch>
<Route exact component={Home} path='/home'></Route>
<Route exact component={Home} path='/'></Route>
<Route exact component={Nav} path='/nav'></Route>
<Route exact component={Nav} path='/nav'></Route>
<Route exact component={Nav} path='/nav'></Route>
</Switch>
</div>
</div>
);
}
export default App;
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import {HashRouter} from 'react-router-dom'
ReactDOM.render(
<React.StrictMode>
<HashRouter><App /></HashRouter>
</React.StrictMode>,
document.getElementById('root')
);
2. 路由参数传递
2.1 动态路由传参
- 需要路由参数占位符,:id
- 触发操作的时候传递具体的参数
- 在具体的组件中使用传递的参数
- 首先要在路由内配置匹配规则Route
- 相关路径的组件需要内部配置Link规则
- 通过props.match.params获取传入的数据对象
// nav 内部配置文件
import React, {Component} from 'react'
import {Link} from 'react-router-dom'
class Nav extends Component {
render () {
return (
<>
<p><Link excat to='/detail/1'>文章1</Link></p>
<p><Link excat to='/detail/2'>文章2</Link></p>
<p><Link excat to='/detail/3'>文章3</Link></p>
</>
)
}
}
export default Nav
// detail 获取传入的数据
import React, {Component} from 'react'
class Detail extends Component {
render () {
return (
<>
{this.props.match.params.id}
</>
)
}
}
export default Detail
// app 根组件
...
<Switch>
...
<Route exact component={Detail} path='/detail/:id'></Route>
</Switch>
...
2.2 查询参数传参
- 在路径后通过xxx?属性名=yyy&…&…进行传参
- 通过props.location.search获取整个查询字段
- 安装qs,通过qs.parse进行转译,ignoreQueryPrefix省略问号
// detail.js
import React, {Component} from 'react'
import qs from 'qs'
class Detail extends Component {
render () {
console.log(this.props);
console.log(qs.parse(this.props.location.search, {ignoreQueryPrefix:true}));
return (
<>
{this.props.match.params.id}
{qs.parse(this.props.location.search, {ignoreQueryPrefix:true}).title}
</>
)
}
}
export default Detail
3. 路由的嵌套
- 在路由组件内部书写新的路由规则和渲染的组件
- 通过props.match.url和props.match.path可以分别动态的获取上一级的路由Link的to路径和Route的path路径,避免了修改父路由而引发的路径错误
- 父组件一定要去除excat属性
// Nav.js
import React, {Component} from 'react'
import {Link, Route} from 'react-router-dom'
import Inner from './inner'
import Outer from './outer'
class Nav extends Component {
render () {
return (
<>
<p><Link to='/nav/1'>文章1</Link></p>
<p><Link to='/nav/2'>文章2</Link></p>
<p><Link to='/nav/3?title="张三"'>文章3</Link></p>
<div>
<div>
{console.log(this.props)}
<Link to={`${this.props.match.url}/inner`}>inner</Link>
<Link to={`${this.props.match.url}/outer`}>outer</Link>
</div>
<div>
<Route path={`${this.props.match.path}/inner`} component={Inner} />
<Route path={`${this.props.match.path}/outer`} component={Outer} />
</div>
</div>
</>
)
}
}
export default Nav
4. 路由跳转及重定向
- 从react-router-dom中引入Redirect组件,属性to为跳转到的路由路径
- 可以通过判断来进行路由的跳转
import React from 'react'
import { Redirect } from 'react-router-dom'
class Inner extends React.Component {
render() {
var isShow = true
if (isShow) {
return (
<Redirect to='/home' />
)
} else {
<p>123</p>
}
}
}
export default Inner
4.1 路由守卫
- 在Route标签中书写path,并且内部可以进行render操作
- render中方法传入的参数是所在路由的所有信息,是子组件的thisprops
import Nav from './components/Nav'
import Home from './components/Home'
import Detail from './components/Detail'
import { Link, Redirect, Route, Switch } from 'react-router-dom'
const auth = {
isAuthor: false,
show: function() {
this.isAuthor = true
}
}
function App() {
return (
<div>
根组件
<div>
<p><Link to='/home'>home</Link>---<Link to='/nav'>nav</Link></p>
<button onClick={() => {auth.show()}}>转换</button>
</div>
<div>
<Switch>
<Route exact component={Detail} path='/nav/:id'></Route>
<Route path='/nav' render={props => {
console.log(props);
if (auth.isAuthor) {
return <Nav {...props} />
} else {
return <Redirect to='/home' />
}
}} />
</Switch>
</div>
</div>
);
}
export default App;
4.2 路由守卫组件
- 目的在于简化路由守卫的操作,单独操作没有什么复杂的,单数数量多就会影响开发
// Guard.js
import React from 'react'
import { Redirect, Route } from 'react-router';
export default class AuthRouterGuard extends React.Component {
render () {
console.log(this.props);
const {component: Component, ...rest} = this.props
return (
<Route {...rest} render={props => {
if (this.props.auth.isAuthor) {
return <Component {...props} />
} else {
return <Redirect to='/home' />
}
}} />
)
}
}
// app.js
import Nav from './components/Nav'
import Home from './components/Home'
import { Link, Route, Switch } from 'react-router-dom'
import AuthRouterGuard from './guard'
const auth = {
isAuthor: false,
show: function() {
this.isAuthor = true
}
}
function App() {
return (
<div>
根组件
<div>
<Link to='/nav'>nav</Link></p>
</div>
<div>
<Switch>
<AuthRouterGuard path='/nav' auth={auth} component={Nav} /
</Switch>
</div>
</div>
);
}
export default App;
5. 路由懒加载
- 懒加载的目的是降低首次页面加载时的性能损耗
- 体现在于一次拆开所有薯片再吃和拆开一包吃一包
- 通过@loadable/component第三方包插件,引入loadComponent方法
- 内部参数为方法,返回值为import引入的组件
import loadComponent from '@loadable/component'
const Home = loadComponent(() => import('./components/Home'))
...
<Route exact component={Home} path='/home'></Route>
...
5. 非路由组件传递路由信息
- 非路由组件为是不需要路由配置的组件,最简单的例子就是一般组件
- 非路由组件使用路由信息需要引入react-router-dom中的插件withRouter,并在导出时包裹组件
// test.js
import React, { Component } from 'react'
import { withRouter } from 'react-router-dom'
class Test extends Component {
render() {
console.log(this.props);
return (
<>
test组件
</>
)
}
}
export default withRouter(Test)
// detail.js
import React, {Component} from 'react'
import qs from 'qs'
import Test from './test'
class Detail extends Component {
render () {
return (
<>
{this.props.match.params.id}
{qs.parse(this.props.location.search, {ignoreQueryPrefix:true}).title}
<Test />
</>
)
}
}
export default Detail