ReactRouter
ReactRouter提供了WebApp中ScreenComponent的导航能力。其提供了三个导航容器可以根据产品需求进行选择:
BrowserRouterHashRouterMemoryRouter
BrowserRouter为传统导航容器,按照浏览器地址栏中的相对路径请求响应的服务页面,这样的导航方式并不适合以组件化开发的WebApp。因WebApp的所有页面都在浏览器中,后台仅提供JSON格式的数据。
HashRouter适合组件化开发的WebApp导航,其导航为以#为地址的相对导航路径,该路径首先在浏览器中进行处理。以下案例均以HashRouter为实现。
MemoryRouter导航容器无地址变化,适合在无地址栏的场景下使用,例如微信中打开一个页面。
基础配置
使用ReactRouter时,首先我们需要对工程中的index.js进行修改。
原index.js文件为:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
在源文件的基础上首先引入ReactRouter中的HashRouter组件:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { HashRouter } from "react-router-dom";
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
然后使用HashRouter对<App/>元素进行包裹,这样App组件就有了Screen导航能力:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { HashRouter } from "react-router-dom";
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(
<HashRouter>
<App />
</HashRouter>,
document.getElementById('root')
);
registerServiceWorker();
构造Screen对象
这里我们构造三个Screen对象:
HomeScreenAScreenBScreen
在HomeScreen对象中,防止两个按钮,点击分别可以跳转到AScreen或BScreen。在AScreen和BScreen中分别放置一个按钮,点击可以返回到HomeScreen。
HomeScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class HomeScreen extends Component {
render() {
return (
<div>
<h1>HomeScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//跳转到AScreen
}}
>
跳转到AScreen
</Button>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到BScreen
}}
>
跳转到BScreen
</Button>
</div>
)
}
}

AScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class AScreen extends Component {
render() {
return (
<div>
<h1>AScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
}}
>
返回HomeScreen
</Button>
</div>
)
}
}

BScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class BScreen extends Component {
render() {
return (
<div>
<h1>BScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
}}
>
返回HomeScreen
</Button>
</div>
)
}
}

构建页面导航
在App组件中,需要构造页面导航规则即,地址和组件直接的映射关系。通过Route进行指定。
import React, { Component } from 'react';
import { Route } from "react-router-dom";
import HomeScreen from './Screen/HomeScreen';
import AScreen from './Screen/AScreen';
import BScreen from './Screen/BScreen';
export default class App extends Component {
render() {
return (
<div>
<Route
exact={true}
path={'/'}
component={HomeScreen}
/>
<Route
path={'/AScreen'}
component={AScreen}
/>
<Route
path={'/BScreen'}
component={BScreen}
/>
</div>
);
}
}
Route下的组件不会全部展示在屏幕,只有请求地址和Route中的path值一致时,才会在屏幕上显示该组件。通过exact属性,可以标准该组件准确匹配路径,否则在请求'/AScreen'时,HomeScreen也会被渲染,因HomeScreen对于的路径为'/',而'/AScreen'也包含'/'。
页面push和goBack
在页面管理中,push和goBack是最常用的两个操作,通过push可以在屏幕上展示当前路径对应的Screen组件,通过goBack可以返回之前的页面。
push和goBack是ReactRouter对象的中history属性的方法,需要通过如下代码获取:
this.props.history.push(path)
this.props.history.goBack()
HomeScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class HomeScreen extends Component {
render() {
return (
<div>
<h1>HomeScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//跳转到AScreen
this.props.history.push('/AScreen')
}}
>
跳转到AScreen
</Button>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到BScreen
this.props.history.push('/BScreen')
}}
>
跳转到BScreen
</Button>
</div>
)
}
}
AScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class AScreen extends Component {
render() {
return (
<div>
<h1>AScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}
BScreen文件:
import React, { Component } from 'react'
import { Button , WhiteSpace } from 'antd-mobile'
export default class BScreen extends Component {
render() {
return (
<div>
<h1>BScreen</h1>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}
页面导航栏
在使用堆栈导航时,需要为页面提供一个NavBar来展示当前页面和提供功能按钮,例如:

组件API:
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| mode | 模式 | string | 'dark' enum{'dark', 'light'} |
| icon | 出现在最左边的图标占位符 | ReactNode | - |
| leftContent | 导航左边内容 | any | 无 |
| rightContent | 导航右边内容 | any | 无 |
| onLeftClick | 导航左边点击回调 | (e: Object): void | 无 |

import React, { Component } from 'react'
import { Button , WhiteSpace,NavBar } from 'antd-mobile'
export default class HomeScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
>Home</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到AScreen
this.props.history.push('/AScreen')
}}
>
跳转到AScreen
</Button>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到BScreen
this.props.history.push('/BScreen')
}}
>
跳转到BScreen
</Button>
</div>
)
}
}

import React, { Component } from 'react'
import { Button , WhiteSpace,NavBar ,Icon} from 'antd-mobile'
export default class AScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => {this.props.history.goBack();}}
>AScreen</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}

import React, { Component } from 'react'
import { Button , WhiteSpace ,NavBar,Icon} from 'antd-mobile'
export default class BScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => {this.props.history.goBack();}}
>AScreen</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}
页面间传值
ReactRouter提供匹配模式进行跳转传值。在定义路由路径是,可以添加/:标记为携带的参数,例如:
<Route
path={'/AScreen/:name'}
component={AScreen}
/>
this.props.history.push('/AScreen'+'tom')
该对象会被展示的组件接收,通过下面代码获取传递的参数
this.props.match.params.name
HomeScreen
import React, { Component } from 'react'
import { Button , WhiteSpace,NavBar } from 'antd-mobile'
export default class HomeScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
>Home</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到AScreen
this.props.history.push('/AScreen'+'tom')
}}
>
跳转到AScreen
</Button>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到BScreen
this.props.history.push('/BScreen')
}}
>
跳转到BScreen
</Button>
</div>
)
}
}
AScreen
import React, { Component } from 'react'
import { Button , WhiteSpace,NavBar ,Icon} from 'antd-mobile'
export default class AScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => {this.props.history.goBack();}}
>AScreen</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<p>{this.props.match.params.name}</p>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}
页面replace
在使用ReactRouter时,可以通过浏览器中地址栏直接访问对于的组件,但在有登录授权的情况下,用户访问没有授权的页面时,应自动调整到登录或指定页面。
ReactRouter中通过replace实现。在组件的componentDidMount()函数中,通过对授权的相关信息进行验证,不符合要求的调用this.props.history.replace('/');或指定页面。
componentDidMount(){
if(判断条件){
this.props.history.replace('/');
}
}
下面代码实现了BScreen组件的登陆判断,BScreen只能通过HomeScreen跳转进入,不能通过地址栏直接进入。
import React, { Component } from 'react'
import { Button , WhiteSpace ,NavBar,Icon} from 'antd-mobile'
export default class BScreen extends Component {
componentDidMount(){
if(!this.props.history.location.state){
this.props.history.replace('/');
}
}
render() {
return (
<div>
<NavBar
mode="light"
icon={<Icon type="left" />}
onLeftClick={() => {this.props.history.goBack();}}
>BScreen</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//返回HomeScreen
this.props.history.goBack();
}}
>
返回HomeScreen
</Button>
</div>
)
}
}
import React, { Component } from 'react'
import { Button , WhiteSpace,NavBar } from 'antd-mobile'
export default class HomeScreen extends Component {
render() {
return (
<div>
<NavBar
mode="light"
>Home</NavBar>
<WhiteSpace/>
<WhiteSpace/>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到AScreen
this.props.history.push('/AScreen',{name:'tom'})
}}
>
跳转到AScreen
</Button>
<WhiteSpace/>
<Button
type={'primary'}
onClick={()=>{
//跳转到BScreen
this.props.history.push('/BScreen',{})
}}
>
跳转到BScreen
</Button>
</div>
)
}
}