因项目升级到0.47.1,之前的navigator不能再使用,so再次研究了react-navigation的使用,先推荐下写的不错的文章~
- ReactNative导航新宠儿react-navigation
- React Native——react-navigation的使用
- React Native未来导航者:react-navigation 使用详解
- react-navigation使用
- React-navigation之StackNavigator
- redux与react-navigation的集成
- React Navigation官方文档
(一)StackNavigator参数详解
const AppNavigator = StackNavigator(StackRouteConfigs, StackNavigatorConfigs);
下面来详细介绍下两个参数:
RouteConfigs
它主要是来配置页面路由的,所有的界面都必须配置在里面。
示例:
const StackRouteConfigs = {
Splash: {
screen: Splash, // 界面
navigationOptions: {
header: null // 无标题栏
}
},
Login: {
screen: Login,
navigationOptions: {
header: null
}
},
Main: {
screen: TabBarNavigator,
navigationOptions: {
header: null
}
},
Registered: {
screen: Registered,
navigationOptions: {
header: null
}
},
LoginSms: {
screen: LoginSms,
navigationOptions: {
header: null
}
}
};
上面用到了一个参数navigationOptions,他是用来配置页面的标题参数。我们可以在路由里面配置参数,像上面的示例一样;你也可以在页面中配置,需要在页面中定义一个静态常量navigationOptions。
navigationOptions
参数说明:
title: 这个即可以作为头部标题,也可以作为返回标题和Tab标题
header: 自定义导航条,系统的导航条会隐藏
headerTitle: 标题
headerBackTitle: 回退标题
headerTruncatedBackTitle: 当回退标题不能显示的时候显示此属性的标题,比如回退标题太长了
headerRight: 定义导航栏右边视图
headerLeft: 定义导航栏左边视图
headerStyle: 定义导航栏的样式,比如背景色等
headerTitleStyle: 定义标题的样式
headerBackTitleStyle: 定义返回标题的样式
headerTintColor: 定义导航条的tintColor,会覆盖headerTitleStyle中的颜色
gesturesEnabled: 定义是否能侧滑返回,iOS默认true,Android默认false
具体页面中配置示例:
static navigationOptions=({
title:'首页',
header:(
<View style={{width:Dimensions.get('window').width,height:64,backgroundColor:'#1B82D1'}}/>
),
headerTitle:(
<View style={{width:60,height:20,backgroundColor:'#F0F'}}/>
),
headerBackTitle:'返回',
headerTruncatedBackTitle:'回退',
headerRight:(
<View>
<Text>right</Text>
</View>
),
headerLeft:(
<View>
<Text>left</Text>
</View>
),
headerStyle: {
backgroundColor:'yellow'
},
headerTitleStyle:{
color:'red'
},
headerBackTitleStyle:{
tintColor:'#E8E8E8'
},
headerTintColor:'#F33',
gesturesEnabled:false
});
StackNavigatorConfig
这个参数主要是配置整个路由的,包括跳转动画,跳转方式等。
参数说明:
initialRouteName: 初始化哪个界面为根界面,如果不配置,默认使用RouteConfigs中的第一个页面当做根界面
initialRouteParams: 初始化根界面参数,主要是给根视图传递一些参数,通过this.props.navigation.state.params可以取到
navigationOptions: 配置默认的navigationOptions
paths: 官方意思是覆盖已经配置的路由,但我没试
mode: 跳转方式,一种是card,默认的,在iOS上是从右到左跳转,在Android上是从下到上,都是使用原生系统的默认跳转方式。一种是modal,只针对iOS平台,模态跳转。
headerMode: 跳转过程中,导航条的动画效果,有三个值,float表示会渐变,类似于iOS的原生效果,screen表示没有渐变。none表示隐藏导航条
cardStyle: 可以统一定义界面的颜色,例如背景色
transitionConfig:配置页面跳转的动画,是一个方法
onTransitionStart: 页面跳转动画即将开始的回调方法
onTransitionEnd: 页面跳转动画结束的回调方法
示例:
const StackNavigatorConfigs = {
initialRouteName: 'Splash', // 初始化哪个界面为根界面
initialRouteParams:{
data:'你好Navigation'
},
navigationOptions:{
headerTintColor:'blue'
},
mode:'card', // 跳转方式:默认的card,在iOS上是从右到左跳转,在Android上是从下到上,都是使用原生系统的默认跳转方式。
headerMode:'screen', // 导航条动画效果:float表示会渐变,类似于iOS的原生效果,screen表示没有渐变。none表示隐藏导航条
cardStyle:({
backgroundColor:'#FFF'
}),
onTransitionStart:((route)=>{
console.log('开始动画');
}),
onTransitionEnd:((route)=>{
console.log('结束动画');
}),
transitionConfig:(()=>({
//因为ios 的导航动画默认是从左到右,所以,这里配置一下动画,使用react-navigation已经实现的从左到右的动画,
//适配Android,不过,需要导入动画
//import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
screenInterpolator:CardStackStyleInterpolator.forHorizontal,
}))
};
注:
CardStackStyleInterpolator.forHorizontal // 从左到右
CardStackStyleInterpolator.forVertical // 从下到上
CardStackStyleInterpolator.forFadeFromBottomAndroid // 从底部淡出
(二)Navigation Prop
属性说明:
navigate:路由方法,主要来启动另一个页面
state:状态,通过state能拿到很多参数。
setParams: 设置参数,记住,一定不要在render方法中调用此方法。
goBack: 返回
dispatch: 给当前界面设置action,会替换原来的跳转,回退等事件
如图所示,是打印的Navigation属性:
navigate
此方法可以传三个参数:navigate(routeName, params, action)
routeName: 页面名称,一定要在路由配置中配置。
params: 传递参数到下一个页面
action: action
- 跳转界面示例:
this.props.navigation.navigate('Registered');
- 传参跳转示例:
this.props.navigation.navigate('LoginSms', {
loginPhone: this.state.phoneNumber
});
另一界面接收该值:
constructor(props) {
super(props);
const loginPhone = this.props.navigation.state.params.loginPhone;
}
state
通过state,我们能拿到传递过来的参数,如上方获取loginPhone示例。
goBack
如果什么都不传,回退到上一个界面;传null,回退到任意界面;传key,可以回退到指定界面。
示例:
this.props.navigation.goBack(); // 回退到上一个界面
this.props.navigation.goBack(null); // 回退到任意界面
this.props.navigation.goBack('Login'); // 回退到指定界面
setParams
设置当前页面的参数,记住,调用此方法一定要在componentDidMount
示例:
componentDidMount() {
var {setParams} = this.props.navigation;
setParams({'loginPhone':'13800001111'});
}
dispatch
所有的Navigation Actions都会返回一个对象,这个对象可以使用navigation.dispatch方法传递到router。
下面的actions是可以使用的:
- Navigate-导航到其他的route
- Reset-使用新的state代替目前的state
- Back-返回上一个state
- Set Params-给定的route设置参数
- Init-如果state没有定义,用来初始化第一个state
action详解
1.Navigate
Navigatie action会使用Navigate action的结果来更新当前的state。
- routeName,字符串,必选项,在app的router里注册的导航目的地的routeName。
- params,对象,可选项,融合进目的地route的参数。
- actions,对象,可选项(高级),如果screen也是一个navigator,次级action可以在子router中运行。在文档中描述的任何actions都可以作为次级action。
import { NavigationActions } from 'react-navigation';
const navigateAction = NavigationActions.navigate({
routeName: 'Splash',
params: {},
action: NavigationActions.navigate({ routeName: 'Login'})
});
this.props.navigation.dispatch(navigateAction);
2.Reset
Reset action删掉所有的navigation state并且使用几个actions的结果来代替。
- index,数组,必选,navigation state中route数组中激活route的index。
- actions,数组,必选项,Navigation Actions数组,将会替代navigation state。
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({ routeName: 'Main'})
]
});
this.props.navigation.dispatch(resetAction);
index参数的使用
index参数被用来定制化当前激活的route。举个栗子:使用两个routes Login和Main给一个基础的stack navigation设置。为了重置route到Main,但是在堆栈中又存放在Login screen之上,你可以这么做:
import { NavigationActions } from 'react-navigation'
const resetAction = NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'Login'}),
NavigationActions.navigate({ routeName: 'Main'})
]
});
this.props.navigation.dispatch(resetAction);
3.Back
返回到前一个screen并且关闭当前screen.backaction creator接受一个可选的参数:
- key:字符串或者空,可选项,如果设定了,navigation将会从设定的key返回;如果是null,navigation将返回到任何地方。
import { NavigationActions } from 'react-navigation'
const backAction = NavigationActions.back({
key: 'Home'
});
this.props.navigation.dispatch(backAction);
4.SetParams
当dispatching setParams的时候,router将会产出一个新的state,这个state是已经改变了特定route的参数,以key作为身份验证。
- params:对象,必选参数,融合进已经存在的route参数中的新参数。
- key:字符串,必选参数,Route的key,应该分配给新的参数。
import { NavigationActions } from 'react-navigation'
const setParamsAction = NavigationActions.setParams({
params: { title: '首页' },
key: 'id-1503398147429-3',
});
this.props.navigation.dispatch(setParamsAction);
(三)自定义NavigationBar
通过对上面的StackNavigator的了解,我们可以使用自定义的NavigationBar,也就是标题栏。
具体自定义NavigationBar的代码就不贴了,我们来说说怎样让自定义的标题栏和StackNavigator建立联系,从而可以使用goBack和navigate等方法进行界面回退、跳转等操作。
我们在自定义NavigationBar的时候,在render方法中会定义一个属性navigator,而我们在其他界面使用自定义的NavigationBar的时候会将这个属性传到NavigationBar中,这样我们就可以在自定义NavigationBar中使用goBack(),navigate等方法了。例如:
loginSms.js
...
render() {
const navigator = this.props.navigation;
const {phoneNumber, smsCode} = this.state;
return (
<View
style={stylesCommon.container}
>
<NavigationBar
title={'登录'}
navigator={navigator}
/>
...
</View>
);
}
...
navigationBar.js
render() {
const {
navigator,
title,
backIconClick,
leftButtonConfig,
style,
...
} = this.props;
let leftButtonConfig = this.props.leftButtonConfig;
if (!leftButtonConfig) {
leftButtonConfig = {
type: 'image',
image: backIcon,
onClick: () => {
if (backIconClick) {
backIconClick();
} else {
if (navigator && !leftButtonHidden) {
console.log('--------navigator-------',navigator);
navigator.goBack();
}
}
},
};
}
return(
...
);
}
注:通过打印'--------navigator-------'发现,navigator传值时一定要传
const navigator = this.props.navigation;
而不能传const {navigate} = this.props.navigation;
后者只是传了navigation属性中的navigate方法,而非整个navigation,我们获取不到goBack()方法,导致报错。