react-native系列(14)导航篇:页面导航StackNavigator参数及使用详解
react-navigation导航是RN官网推荐使用的导航插件,目前最新版本为3.x,它包括3种类型的导航:
- StackNavigator
- TabNavigator
- DrawerNavigator
本篇主要介绍的是StackNavigator,假设你已经对它的用法已经有了基本的认识,或重新去官网看一下
官网地址:https://reactnavigation.org/zh-Hans/
StackNavigator嵌套
一般app的导航都只有一个导航堆栈,结构如下:
有些逻辑比较复杂的app,存在导航嵌套的情况,结构如下:
这种情况下,可以使用StackNavigator嵌套,把子导航堆栈做为根导航堆栈的其中一个页面:
// 子导航堆栈const itemStack= createStackNavigator(
{
Screen1: { screen: Screen1}
},
...
);
// 根导航堆栈
const rootStack = createStackNavigator(
{
Screen1: { screen: itemStack}
},
...
);
createStackNavigator函数详解
createStackNavigator函数用于创建Stack导航,它包含了两个参数对象:第一个参数用来配置路由页面,第二个参数用来配置路由的其它信息。
创建时,相关参数详解如下:
const rootStack = createStackNavigator( // 路由页面
{
Page1: { screen: PageView1 },
Page2: { screen: PageView2, params: {}} // 第二个参数params为页面入参
},
// 路由其它信息
{
initialRouteName: 'Page1', // 初始页,必须是路由配置页面中的某一个
initialRouteParams: {}, // 初始页入参
// mode: '', // 系统的页面切换动画风格,目前只有默认card和模态风格modal两种。但本人3.X版本测试结果是仅剩modal一种,一般这个配置不做设置
// headerMode: 'none' // none时表示隐藏头部的导航栏,默认情况下不做设置
// 导航栏配置
defaultNavigationOptions: {
headerStyle:{}, // 导航栏样式
headerTitle:'', // 或使用title,导航栏标题
headerTitleStyle:{}, // 导航栏标题样式
headerLeft:(<View />), // 导航栏左边如返回等的显示容器
headerRight:(<View />), // 导航栏右边如工具等的显示容器
gesturesEnabled: false, // 是否支持滑动返回手势,iOS默认支持,安卓默认关闭
},
// 自定义页面切换动画配置
transitionConfig: () => ({
// some code
})
}
);
测试代码:
import React, { Component } from 'react';import { View, Easing, Animated } from 'react-native';
import { createStackNavigator, createAppContainer } from 'react-navigation';
import { AuthScreen, ListScreen, ItemScreen, ModalScreen } from './StackScreen';
const mainNavigator = createStackNavigator(
{
Auth: { screen: AuthScreen },
List: { screen: ListScreen, params: {defaultParam: 'this is defaultParam'}},
Item: { screen: ItemScreen }
},
{
initialRouteName: 'Auth',
initialRouteParams: { param: 'this is initParam' },
defaultNavigationOptions: {
gesturesEnabled: false
},
// 类似于微信的左右切换路由页
transitionConfig: () => ({
transitionSpec: {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
},
screenInterpolator: sceneProps => {
const {layout, position, scene} = sceneProps;
const {index} = scene;
const Width = layout.initWidth;
//沿X轴平移
const translateX = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [Width, 0, -(Width)], // Width,0指新页面进入坐标变化; 0,-(Width)是指旧页面推出坐标变化
});
//透明度
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return {opacity, transform: [{translateX}]};
}
})
}
);
// 根导航堆栈
const rootStack = createStackNavigator(
{
Main: { screen: mainNavigator },
Modal: { screen: ModalScreen } // modal屏操作,常会使用不同的屏间切换样式,且隐藏头部导航栏
},
{
initialRouteName: 'Main',
initialRouteParams: { defaultParam: 'defaultParam' },
mode: 'modal', // 定义跳转风格为modal
headerMode: 'none' // 隐藏该导航堆栈中的标题栏
}
);
const AppNavigatorContainer = createAppContainer(rootStack);
class StackNavigator extends Component {
render(){
return(
<View style={{flex:1}}>
<AppNavigatorContainer />
</View>
);
}
}
export default StackNavigator;
这段代码用到了导航嵌套,目的是把模态框弹窗Modal也作为导航的一部分。有些人会说也可以使用Modal组件,为什么写在这里做为导航的一个页面?因为如果不把Modal做为一个页面,那么模态框仅会弹出在导航栏下的页面容器中而不会遮挡导航栏。
导航过程效果:
NavigationOptions
navigationOptions为静态函数,写在路由页中,主要用于设置导航栏样式,配置参数:
static navigationOptions = ({ navigation }) => ({ header: null, // 为null时表示隐藏导航栏
headerStyle:{}, // 导航栏样式
headerTitle:'', // 或使用title,导航栏标题
headerTitleStyle:{}, // 导航栏标题样式
headerLeft:(<View />), // 导航栏左边如'返回'的显示容器
headerRight:(<View />), // 导航栏右边如'其它辅助功能'的显示容器
gesturesEnabled: false, // 是否支持滑动返回手势,iOS默认支持,安卓默认关闭
})
测试代码:
import React, { Component } from 'react';import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
class ListScreen extends Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: 'ListScreen',
headerStyle: {
backgroundColor: '#f4511e'
},
headerTitleStyle: {
flex: 1,
textAlign: 'center',
color: '#FFFFFF',
fontSize: 26
},
headerLeft:(
<TouchableOpacity
style={styles.buttonContainer}
onPress={()=>{navigation.goBack();}}
>
<Text style={styles.headerLeftTextStyle}>返回{navigation.getParam('prevScreenTitle','为空时显示这段文字')}</Text>
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity
style={styles.buttonContainer}
onPress={()=>{navigation.navigate('Item', { prevScreenTitle: 'ListScreen' });}}
>
<Text style={styles.headerRightTextStyle}>进入ItemScreen</Text>
</TouchableOpacity>
)
})
render(){
const { navigation } = this.props;
console.log(navigation.getParam('defaultParam'));
return(
<View style={styles.viewStyle}>
<Text>This is ListScreen!</Text>
</View>
);
}
}
ListScreen.propTypes = {
navigation: PropTypes.object
};
const styles = StyleSheet.create({
viewStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
buttonContainer: {
backgroundColor: '#FFFFFF',
justifyContent: 'center',
alignItems: 'center',
padding: 5
},
headerLeftTextStyle: {
color: 'blue'
},
headerRightTextStyle: {
color: 'green'
}
});
export default ListScreen;
导航栏样式效果:
页面跳转及参数传递
路由页面跳转使用navigation.navigate函数,第一个参数为跳转的页面名称,第二个参数为传递的参数:
navigation.navigate('List', {param:'some data'});
关于接收参数,无论是在创建时设置的默认入参还是跳转页面时传递的参数,都通过getParam函数来获取,第一个参数为参数名称,第二个参数为当没有参数时,以该参数内容作为入参:
const initData = navigation.getParam('param','当没有获取到参数时显示这段文字')
返回上一个页面使用goBack函数:
navigation.goBack()
导航栏与页面内容的数据交互
页面内容通过navigation.setParams来设置导航栏所需数据:
state = { day: '星期一'
}
componentDidMount() {
this.props.navigation.setParams({ day: this.state.day});
}
导航栏通过navigation.getParam来获取数据:
const day = navigation.getParam('day'); // 星期一
测试代码:
import React, { Component } from 'react';import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
class ItemScreen extends Component {
static navigationOptions = ({ navigation }) => ({
headerTitle: 'ItemScreen',
headerStyle: {
backgroundColor: '#f4511e'
},
headerTitleStyle: {
flex: 1,
textAlign: 'center',
color: '#FFFFFF',
fontSize: 26
},
headerLeft:(
<TouchableOpacity
style={styles.buttonContainer}
onPress={()=>{navigation.goBack();}}
>
<Text style={styles.headerLeftTextStyle}>返回{navigation.getParam('prevScreenTitle','为空时显示这段文字')}</Text>
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity
style={styles.buttonContainer}
onPress={navigation.getParam('increaseCount')}
>
<Text style={styles.headerRightTextStyle}>计数器 +1</Text>
</TouchableOpacity>
)
})
constructor(props){
super(props);
this.state = {count:0};
}
componentDidMount() {
this.props.navigation.setParams({ increaseCount: this._increaseCount });
}
_increaseCount = () => {
this.setState({ count: this.state.count + 1 });
};
render(){
const { navigation } = this.props;
return(
<View style={styles.viewContainer}>
<Text>计数器结果:{this.state.count}</Text>
<TouchableOpacity
style={[styles.buttonContainer, styles.modalStyle]}
onPress={()=> navigation.navigate('Modal')}
>
<Text style={styles.modalTextStyle}>进入ModalScreen</Text>
</TouchableOpacity>
</View>
);
}
}
ItemScreen.propTypes = {
navigation: PropTypes.object
};
const styles = StyleSheet.create({
viewContainer:{
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
buttonContainer: {
backgroundColor: '#FFFFFF',
justifyContent: 'center',
alignItems: 'center',
padding: 5
},
headerLeftTextStyle: {
color: 'blue'
},
headerRightTextStyle: {
color: 'green'
},
modalStyle: {
marginTop: 10,
borderWidth: 1,
padding: 5
},
modalTextStyle: {
color: 'red'
},
});
export default ItemScreen;
数据交互效果:
页面切换动画
可在transitionConfig属性配置,不了解结构可以看开篇处的createStackNavigator函数详解,详解测试代码中已经定义了一种动画效果。这里再贴出一份上下切换的动画作为比较:
// 上下切换路由页transitionConfig: () => ({
transitionSpec: {
duration: 300,
easing: Easing.out(Easing.poly(4)),
timing: Animated.timing,
},
screenInterpolator: sceneProps => {
const { layout, position, scene } = sceneProps;
const { index } = scene;
const height = layout.initHeight;
//沿Y轴平移
const translateY = position.interpolate({
inputRange: [index - 1, index, index + 1],
outputRange: [height, 0, 0],
});
//透明度
const opacity = position.interpolate({
inputRange: [index - 1, index - 0.99, index],
outputRange: [0, 1, 1],
});
return { opacity, transform: [{ translateY }] };
},
})
效果:
若要自定义切换动画,可以使用先了解一下Animated库。也可以参考 react-native系列(13)动画篇:Animated动画库和LayoutAnimation布局动画详解
(小贴士)react-navigation默认情况下负责为您处理 Android 返回按钮,即设备屏幕外的返回键,如果没有处理或不符合您的期望,可以使用RN官网中的BackHandler函数监听实现。
以上就是StackNavigator的一些实用经验,希望能对你有一定参考价值。
以上是 react-native系列(14)导航篇:页面导航StackNavigator参数及使用详解 的全部内容, 来源链接: utcz.com/z/382497.html