最近在使用React Native开发Android端的一些东西,在使用导航条的时候,由于跟IOS的不一样特写此篇文章介绍一下我的使用过程
本博文中使用React Navigation是基于React Native和Redux相结合使用的前提,而且本文中使用的React Navigation是V2版本,相比较V1版本有些许差别。至于React Native和Redux的使用可以在网上搜索,有好多写的不错的博文,在这里我就不再叙述。
一、Navigator组件
首先是写Navigator的书写。这里只是用到StackNavigator组件,至于其他Navigator大同小异,如果日后有时间我再做补充。
import
React, {
Component }
from
'react';
import {
createStackNavigator,
}
from
'react-navigation'
import {
connect }
from
'react-redux';
import
AppHome
from
'./AppHome';
import
Splash
from
'./Splash';
import
Login
from
'./centerContent/login';
import {
toastShort }
from
'../utils/TostUtil';
import
NewsPage, {}
from
'./centerContent/News'
import {
NavigationActions }
from
'react-navigation';
import {
addListener}
from
'../utils/MyNaviRedux'
import {
Platform,
BackHandler,
BackAndroid,
StatusBar,
View
}
from
'react-native';
// 路由表
const
RouteConfigs = {
home: {
screen:
AppHome },
Splash: {
screen:
Splash,
navigationOptions: {
header:
null,
}
},
Login: {
screen:
Login },
NewsPage: {
screen:
NewsPage},
}
//初始页
const
StackNavigatorConfigs = {
initialRouteName:
'Splash',
};
export
const
Navigator =
createStackNavigator(
RouteConfigs,
StackNavigatorConfigs);
class
NavigatorComponent
extends
Component {
constructor(
props) {
super(
props);
this.
goBackAndroid =
this.
goBackAndroid.
bind(
this);
this.
goback=
this.
goback.
bind(
this);
}
render() {
return (
<
Navigator
navigation=
{{
dispatch:
this.
props.
dispatch,
state:
this.
props.
nav,
addListener,
}
}
/>
);
}
goBackAndroid() {
const {
routes } =
this.
props.
nav;
const {
nav} =
this.
props;
const {
dispatch} =
this.
props;
console.
log(
nav.
index);
if (
nav.
index===
0) {
if (
this.
lastBackPressed &&
this.
lastBackPressed +
2000 >=
Date.
now()) {
//最近2秒内按过back键,可以退出应用。
BackAndroid.
exitApp();
return
false;
}
this.
lastBackPressed =
Date.
now();
toastShort(
"再按一次退出应用");
return
true;
}
dispatch(
NavigationActions.
back())
return
true;
}
goback(){
const {
dispatch } =
this.
props;
if (
dispatch) {
dispatch(
NavigationActions.
back({})
);
}
}
componentWillMount() {
if (
Platform.
OS ===
'android') {
BackHandler.
addEventListener(
'hardwareBackPress',
this.
goBackAndroid);
}
}
componentWillUnmount() {
if (
Platform.
OS ===
'android') {
BackHandler.
addEventListener(
'hardwareBackPress',
this.
goBackAndroid);
}
}
}
function
mapStateToProps(
state,
ownProps) {
const {
nav } =
state;
return {
nav
}
}
export
default
connect(
mapStateToProps)(
NavigatorComponent);
1、首先我定义了一个路由表,一个初始化页面,并使用createStackNavigator创建Navigator 。在V2版本里面已经不再使用StackNavigator方法直接创建导航栏对象,并且注意这里使用路由表和初始化页面变量来初始化StackNavigator,否则在创建reducer的时候会出现null is not an object (evaluating 'action.routeName')这样一个错误。
2、在Navigation的V2版本中不再使用addNavigationHelpers来为Navigator中navigation属性添加方法属性,而且需要田间一个addlistener属性。这个addlistener属性必须添加,否则会有一个错误。下面来说一说addListener是怎么创建出来的。
二、为Redux的Store创建中间件
1、首先我定义了一个工具MyNaviRedux用于创建addlinstener和Store的中间件
import {
createReactNavigationReduxMiddleware,
createReduxBoundAddListener
}
from
'react-navigation-redux-helpers';
// 注意: createReactNavigationReduxMiddleware 必须在 createReduxBoundAddListener 之前执行
const
reactMiddleware =
createReactNavigationReduxMiddleware(
"root",
state
=>
state.
nav,
);
const
addListener =
createReduxBoundAddListener(
"root");
export {
reactMiddleware,
addListener
};
1、需要react-navigation-redux-helpers这个包,当然我直接使用npm install react-navigation-redux-helpers命令就将次包给安装了
2、必须强调createReactNavigationReduxMiddleware一定要在createReduxBoundAddListener之前调用,否则报错。
3、这里创建了addListener 变量,这个就是在上一步操作在初始化Navigator中需要使用addListener .
4、这里创建了Redux的Store要使用的中间件reactMiddleware ,在后面添加中间件将会使用到
2、为Redux的Store添加中间件reactMiddleware
import {
createStore,
applyMiddleware}
from
'redux';
import
thunkMiddleware
from
'redux-thunk';
import
rootReducer
from
'../reducers/index';
import {
reactMiddleware}
from
'../utils/MyNaviRedux'
const
createStoreWithMiddleware =
applyMiddleware(
thunkMiddleware,
reactMiddleware)(
createStore);
export
default
function
configureStore(
initialState) {
const
store =
createStoreWithMiddleware(
rootReducer,
initialState);
return
store;
}
这里只需要将上一步创建的
reactMiddleware引入,然后在
applyMiddleware
(
thunkMiddleware
,
reactMiddleware
)(
createStore
);方法中添加就好了。至此还差最后一步,接下来就是创建reducer。
三、创建Navigation的reducer
import {
NavigationActions,
StackNavigator,
StackActions}
from
"react-navigation";
import {
Navigator}
from
'../pages/StackNavigatorComponent';
const
initialState =
Navigator.
router.
getStateForAction(
Navigator.
router.
getActionForPathAndParams(
'home'));
export
default
function
NavReducer(
state=
initialState,
action) {
let
nextState;
switch (
action.
type) {
case
'Login':
nextState =
Navigator.
router.
getStateForAction(
NavigationActions.
navigate({
routeName:
'Login'}),
state
);
break;
case
'main':
nextState =
Navigator.
router.
getStateForAction(
NavigationActions.
navigate({
routeName:
'AppHome'})
,
state
);
break;
case
'NewsPage':
nextState =
Navigator.
router.
getStateForAction(
NavigationActions.
navigate({
routeName:
'NewsPage'})
,
state
);
break;
default:
nextState =
Navigator.
router.
getStateForAction(
action,
state);
break;
}
return
nextState ?
nextState :
state;
}
- 首先我引入了在Navigator组件中创建的Navigator对象
- 使用跳转到home页的aciton初始化变量
- 然后就是根据dispatch中传递过来的type类型来进行相应的跳转操作
在上一步操作完成之后需要就是将此reducer添加到Redux
import {
combineReducers}
from
'redux';
import
login
from
'./LoginReducer';
// import nav from './NavReducer';
import
NavReducer
from
'./NavReducer'
import
GetNewsData
from
'./NewsListDataReducer'
const
rootReducer =
combineReducers({
login,
nav:NavReducer,
GetNewsData
})
export
default
rootReducer;
在这里引入上一步操作创建的Reducer加入到rootReducer中即可。
可能遇到的错误如下:
Cannot listen for a key that isn't associated with a Redux store. First call createReactNavigationReduxMiddleware so that we know when to trigger your listener
我在讲解创建中间件的时候有说道:在工具MyNaviRedux中createReactNavigationReduxMiddleware一定要在createReduxBoundAddListener之前调用。