react-router是路由組件核心潦匈,而react-router-dom是在react-router的基礎(chǔ)上擴(kuò)展了dom組件Link、HashRouter等赚导。
1.react-router-dom安裝
npm install react-router-dom --save
2.基礎(chǔ)使用方法
直接貼代碼历等,首先需要從reacr-router-dom中引出所需的組件,這里采用hash模式路由辟癌,此次我再router.js文件中配置了路由規(guī)則寒屯,包括path和component,之后循環(huán)出路由組件黍少。其中switch組件用于選擇其下的匹配路由進(jìn)行展示寡夹,其中還包含Redirect重定向組件,當(dāng)所有的路由都無法匹配時(shí)厂置,會(huì)重定向到該組件配置的to路由菩掏。
// App.jsx
import React, {
Component
} from 'react';
import router from './router/index';
import { HashRouter, Route, Switch, Redirect } from 'react-router-dom';
class App extends Component {
constructor(props) {
super(props);
}
initRouter () {
let routerList = router.map(item => (
<Route
component={item.component}
exact
key={item.path}
path={item.path}
></Route>
));
return routerList;
}
render () {
return (
<div className="App">
<HashRouter>
<Switch>
{this.initRouter.bind(this)()}
<Redirect
path="/*"
to="/home"
></Redirect>
</Switch>
</HashRouter>
</div >
);
}
}
export default App;
以下為路由配置文件,其中引入了@loadable/component包用于路由懶加載昵济,優(yōu)化首頁加載速度
// router.js路由配置
// 路由懶加載方式
import loadable from '@loadable/component'
const router = [{
path: '/home',
component: loadable(() => import('../pages/HomePage'))
},
{
path: '/detail',
component: loadable(() => import('../pages/DetailPage'))
}
];
export default router;
3.路由跳轉(zhuǎn)
方法一:使用react-router-dom提供的Link組件進(jìn)行跳轉(zhuǎn)
<Link to="/about">About</Link>
方法二:使用react-router-dom封裝的push智绸、goBack、go访忿、replace方法進(jìn)行跳轉(zhuǎn)
// 可以使用對(duì)象也可使用路徑path
this.props.history.push({
pathname: '/detail'
});
this.props.history.push( '/detail');
// 類似vue的go
this.props.history.go(-1);
// 返回上一路由
this.props.history.goBack();
// 替換當(dāng)前路由防止出現(xiàn)死循環(huán)
this.props.history.replace('/detail');
4.路由傳參
方法一:params瞧栗,利用此方法傳遞的參數(shù)會(huì)保留在瀏覽器的地址欄,刷新頁面參數(shù)與任然存在海铆,從match中取值迹恐,建議采用這種方法。
<Route path='/path/:name/:id' component={Demo}/>
<link to="/path/lisi/2">xxx</Link>
this.props.history.push({pathname:"/path/" + name + id});
讀取參數(shù)用:this.props.match.params // { name: 'lisi', id:'2' }
方法二:query卧斟,此方法傳遞的參數(shù)不會(huì)存在于地址欄殴边,故刷新頁面參數(shù)會(huì)丟失,從location中取值珍语。
<Route path='/query' component={Demo}/>
<Link to={{ path : ' /query' , query : { name : 'lisi' }}}>
this.props.history.push({pathname:"/query",query: { name : 'lisi' }});
讀取參數(shù)用: this.props.location.query // { name:'lisi' }
方法三:state锤岸,此方法和query方法相似,同樣是隱式傳遞板乙,從location中取值是偷,不會(huì)存在于地址欄,刷新頁面參數(shù)會(huì)丟失亡驰,但是state中的數(shù)據(jù)是加密傳輸?shù)南停^安全。
<Route path='/sort ' component={Demo}/>
<Link to={{ path : ' /sort ' , state : { name : 'lisi' }}}>
this.props.history.push({pathname:"/sort ",state : { name : 'lisi' }});
讀取參數(shù)用: this.props.location.query // { name:'lisi' }
5.使用react.lazy實(shí)現(xiàn)路由懶加載
前面我們利用的是loadable-components插件實(shí)現(xiàn)的路由懶加載凡辱,在react16.6.0后,react引入了lazy方法栗恩,用于動(dòng)態(tài)加載組件透乾,由此我們可以利用它來實(shí)現(xiàn)路由懶加載。
// 路由懶加載方式
// 利用loadable/component動(dòng)態(tài)加載組件
// import loadable from '@loadable/component'
// const router = [{
// path: '/home',
// component: loadable(() => import('../pages/HomePage'))
// },
// {
// path: '/detail',
// component: loadable(() => import('../pages/DetailPage'))
// },
// {
// path: '/mobx',
// component: loadable(() => import('../pages/testmobx'))
// }
// ];
// 利用react.lazy動(dòng)態(tài)加載組件
import { lazy } from 'react'
const router = [{
path: '/home',
component: lazy(() => import('../pages/HomePage'))
},
{
path: '/detail',
component: lazy(() => import('../pages/DetailPage'))
},
{
path: '/mobx',
component: lazy(() => import('../pages/testmobx'))
}
];
export default router;
組件渲染,需要注意的是使用react.lazy動(dòng)態(tài)加載路由必須指定Suspense乳乌,并添加回調(diào)渲染組件捧韵,用于在加載組件過程中顯示loading效果,如果不指定該組件汉操,react會(huì)報(bào)錯(cuò)
import React, {
Component,
Suspense
} from 'react';
import router from './router/index';
import { HashRouter, Route, Switch, Redirect } from 'react-router-dom';
class App extends Component {
initRouter () {
let routerList = router.map(item => (
<Route
component={item.component}
exact
key={item.path}
path={item.path}
></Route>
));
return routerList;
}
render () {
return (
<div className="App">
<HashRouter>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
{this.initRouter.bind(this)()}
<Redirect
path="/*"
to="/home"
></Redirect>
</Switch>
</Suspense>
</HashRouter>
</div >
);
}
}
export default App;
6.使用react-router-config實(shí)現(xiàn)嵌套路由
react-router-config是為react-router寫的優(yōu)雅的配置路由表的插件
react-router-config地址
其實(shí)上面的路由也是采用路由配置的方式組織的再来,但是不夠優(yōu)雅,也不支持嵌套路由磷瘤,使用react-router-config將方便我們進(jìn)行路由嵌套配置芒篷。
1.修改路由配置表如下,其中Home組件下嵌套了TestMobx組件,并接收id參數(shù)
注意:嵌套路由的父組件(此處是Home組件)不可以添加 exact: true選項(xiàng)采缚,添加后會(huì)導(dǎo)致子路由無法匹配针炉,無法實(shí)現(xiàn)嵌套路由
const router = [{
path: '/home',
component: lazy(() => import('../pages/HomePage')),
routes: [{
path: '/home/mobx/:id',
component: lazy(() => import('../pages/testmobx'))
}]
},
{
path: '/detail',
component: lazy(() => import('../pages/DetailPage')),
exact: true
},
];
export default router;
2.修改路由組件利用renderRoutes 函數(shù)渲染route組件
import React, {
Component,
Suspense
} from 'react';
import router from './router/index';
import { HashRouter, Route, Switch, Redirect,Link } from 'react-router-dom';
import { renderRoutes } from "react-router-config";
class App extends Component {
initRouter () {
let routerList = router.map(item => (
<Route
component={item.component}
exact
key={item.path}
path={item.path}
></Route>
));
return routerList;
}
render () {
return (
<div className="App">
<HashRouter>
<ul>
<li><Link to="/home">首頁</Link></li>
<li><Link to="/detail">詳情頁</Link></li>
<li><Link to="/home/mobx/123">嵌套</Link></li>
</ul>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
{renderRoutes(router)}
<Redirect
path="/*"
to="/home"
></Redirect>
</Switch>
</Suspense>
</HashRouter>
</div >
);
}
}
export default App;
3.想要實(shí)現(xiàn)嵌套,必不可少的我們需要在父級(jí)組件出添加renderRoutes渲染this.props.route.routes其中的子組件扳抽。
import React, { Component } from 'react';
import { Button } from 'antd';
import { renderRoutes } from "react-router-config";
class HomePage extends Component {
render () {
return (
<div>
<div >homePage</div>
{/* 此處的routes應(yīng)該是配置中的子組件篡帕,如果路由配置中配置的children,那么這里就是 this.props.route.children*/}
{renderRoutes(this.props.route.routes, { someProp: "these extra props are optional" })}
</div>
);
}
}
export default HomePage;