React-navigation之StackNavigator
1 先给出资料:
2 导航栏分类
按使用形式主要分三部分:
(1) StackNavigator
:
类似于普通的Navigator,实现不同的页面进行跳转
(2) TabNavigator
:
相当于里面的TabBarController,屏幕上方的标签栏,不同的tabs互相切换。
(3) DrawerNavigator
:
抽屉效果,侧边滑出
今天主要学习StackNavigator,另外两个随后跟上。
3 navigationOptions
在这一块我是狠狠的被坑了一把,资料上给出的navigationOptions是这样的:
-
title
: 导航栏的标题 -
header
: 导航栏设置对象visible
: 导航栏是否显示title
: 导航栏的标题, 可以是字符串也可以是个组件backTitle
: 左上角的返回键文字, 默认是上一个页面的titleright
: 导航栏右按钮left
: 导航栏左按钮style
: 导航栏的styletitleStyle
: 导航栏的title的styletintColor
: 导航栏颜色
-
cardStack
: 配置card stackgesturesEnabled
: 是否允许右滑返回,在iOS上默认为true,在Android上默认为false
按照说明设置各种属性,结果是各种无效,查找资料也没有找到好的实例,好吧,还是回来看官方文档,哎,才发现navigationOptions变样了,可能是版本更新了或编辑器的问题的,在这里我用的编辑器是Sublime Text,反正是各种无效,我们来看官网的navigationOptions:
-
title
: 导航栏的标题 -
header
: 导航栏设置对象 - headerTitle: 导航栏的标题, 可以是字符串也可以是个组件
- headerBackTitle: 左上角的返回键文字, 默认是上一个页面的title,设置这个属性会覆盖掉title的值
- headerRight: 导航栏右按钮
headerLeft
: 导航栏左按钮headerStyle
: 导航栏的styleheaderTitleStyle
: 导航栏的title的styleheaderTintColor
: 返回按钮的颜色- headerPressColorAndroid :按压返回按钮显示的颜色 安卓系统 >= 5.0才有效。
- gesturesEnabled :是否允许右滑返回,在iOS上默认为true,在Android上默认为false
使用事例:
ChatScreen.navigationOptions = ({navigation}) => { console.log("---------navigation------------>"); console.log(navigation); //Object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function} return { // 展示数据 "`" 不是单引号 title: `Chat with ${navigation.state.params.user}`, // 导航栏的标题, 可以是字符串也可以是个组件 会覆盖 title 的值 // headerTitle : '返回', //右边按钮 headerRight:( <View> <Button title="点我" onPress={() => alert("hello")} /> </View> ), //左上角的返回键文字, 默认是上一个页面的title IOS 有效 headerBackTitle : "返回", //导航栏的style headerStyle: { backgroundColor: '#fff' }, //导航栏的title的style headerTitleStyle: { color: 'green', //居中显示 alignSelf : 'center', }, //按压返回按钮显示的颜色 API > 5.0 有效 headerPressColorAndroid : 'blue', //返回按钮的颜色 headerTintColor : 'red', //是否允许右滑返回,在iOS上默认为true,在Android上默认为false gesturesEnabled: true, }; };
4 StackNavigatorConfig
参数:
initialRouteName
: 设置默认的页面组件,必须是上面已注册的页面组件initialRouteParams
: 初始路由的参数navigationOptions
: 屏幕导航的默认选项-
paths
: RouteConfigs里面路径设置的映射 -
mode
: 页面切换模式:card
: 普通app常用的左右切换modal
: 上下切换
-
headerMode
: 导航栏的显示模式:float
: 无透明效果, 默认screen
: 有渐变透明效果, 如微信QQ的一样none
: 隐藏导航栏
-
cardStyle
: 样式 -
onTransitionStart
: 页面切换开始时的回调函数 onTransitionEnd
: 页面切换结束时的回调函数
这个到没有什么变化。
5 API
StackNavigator(RouteConfigs, StackNavigatorConfig)
参数一:配置你需要跳转的导航界面,参数二:可选,配置属性(参见4)。
例:
// MyFirstProject 是你的react native 项目名 注意: 这块代码要放置到HomeScreen,ChatScreen...的下面否则会出错:Home不存在。 const MyFirstProject = StackNavigator({ Home: { screen: HomeScreen }, Chat: { screen: ChatScreen }, // navigationOptions: {} // 此处设置了, 会覆盖组件内的`static navigationOptions`设置. },{ initialRouteName: 'Home', // 默认显示界面 //导航栏相关设置项 // header:{ // //导航栏可见 // visible : false, // //左上角的返回键文字, 默认是上一个页面的title // backTitle : "返回", // //导航栏的style // headerStyle: { // backgroundColor: '#fff' // }, // //导航栏的title的style // titleStyle: { // color: 'green' // } // }, // title : 'home', // //导航栏的style // headerStyle: { // backgroundColor: '#fff' // }, // //导航栏的title的style // headerTitleStyle: { // color: 'blue', // //居中显示 // alignSelf : 'center', // }, // //是否允许右滑返回,在iOS上默认为true,在Android上默认为false // cardStack: { // gesturesEnabled: true, // }, onTransitionStart: ()=>{ console.log('导航栏切换开始'); }, // 回调 onTransitionEnd: ()=>{ console.log('导航栏切换结束'); }, // 回调 });
6 数据传递分析
import React from 'react'; import { AppRegistry, Text, View, Button, } from 'react-native'; import { StackNavigator } from 'react-navigation'; //第一个页面 class HomeScreen extends React.Component { // static navigationOptions = { // //标题 // title: 'FirstScreen', // //是否允许右滑返回,在iOS上默认为true,在Android上默认为false // cardStack: { // gesturesEnabled: true, // }, // }; render() { const { navigate } = this.props.navigation; // navigate 是什么鬼 就是下面的这块代码 可见 navigate 是个function对象 参数一 是要跳转的页面名字 例如:Chat 参数2:要传递的参数 参数3: 一般不用 // function navigate(routeName, params, action) { // return navigation.dispatch(_NavigationActions2.default.navigate({ // routeName: routeName, // params: params, // action: action // })); console.log(navigate); return ( <View> <Text>Hello, Navigation!</Text> <Text></Text> <Button //点击跳转到界面二,并传递参数 { user: 'Lucy' } onPress={() => navigate('Chat', { user: 'Lucy' })} title="去 ChatScreen界面" /> <Text></Text> </View> ); } } // // 这样也是可以 // HomeScreen.navigationOptions = { // //标题 // title: 'FirstScreen', // //是否允许右滑返回,在iOS上默认为true,在Android上默认为false // cardStack: { // gesturesEnabled: true, // }, // }; // 第二个页面 class ChatScreen extends React.Component { static navigationOptions = ({navigation}) => ({ // 展示数据 "`" 不是单引号 title: `Chat with ${navigation.state.params.user}`, }); render() { // The screen's current route is passed in to `props.navigation.state`: 传过来的对象:{ user: 'Lucy' } const { params } = this.props.navigation.state; console.log(this.props.navigation); //object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function} console.log(this.props.navigation.state); //Object {params: Object, key: "id-1498014888408-1", routeName: "Chat"} console.log("-----------params----------->"); console.log(params); //打印结果{user: "Lucy"} return ( <View> <Text>Chat with {params.user}</Text> </View> ); } } ChatScreen.navigationOptions = ({navigation}) => { console.log("---------navigation------------>"); console.log(navigation); //Object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function} return { // 展示数据 "`" 不是单引号 title: `Chat with ${navigation.state.params.user}`, // 导航栏的标题, 可以是字符串也可以是个组件 会覆盖 title 的值 // headerTitle : '返回', //右边按钮 headerRight:( <View> <Button title="点我" onPress={() => alert("hello")} /> </View> ), //左上角的返回键文字, 默认是上一个页面的title IOS 有效 headerBackTitle : "返回", //导航栏的style headerStyle: { backgroundColor: '#fff' }, //导航栏的title的style headerTitleStyle: { color: 'green', //居中显示 alignSelf : 'center', }, //按压返回按钮显示的颜色 API > 5.0 有效 headerPressColorAndroid : 'blue', //返回按钮的颜色 headerTintColor : 'red', //是否允许右滑返回,在iOS上默认为true,在Android上默认为false gesturesEnabled: true, }; }; // MyFirstProject 是你的react native 项目名 注意: 这块代码要放置到HomeScreen,ChatScreen...的下面否则会出错:Home不存在。 const MyFirstProject = StackNavigator({ Home: { screen: HomeScreen }, Chat: { screen: ChatScreen }, // navigationOptions: {} // 此处设置了, 会覆盖组件内的`static navigationOptions`设置. },{ initialRouteName: 'Home', // 默认显示界面 //导航栏相关设置项 // header:{ // //导航栏可见 // visible : false, // //左上角的返回键文字, 默认是上一个页面的title // backTitle : "返回", // //导航栏的style // headerStyle: { // backgroundColor: '#fff' // }, // //导航栏的title的style // titleStyle: { // color: 'green' // } // }, // title : 'home', // //导航栏的style // headerStyle: { // backgroundColor: '#fff' // }, // //导航栏的title的style // headerTitleStyle: { // color: 'blue', // //居中显示 // alignSelf : 'center', // }, // //是否允许右滑返回,在iOS上默认为true,在Android上默认为false // cardStack: { // gesturesEnabled: true, // }, onTransitionStart: ()=>{ console.log('导航栏切换开始'); }, // 回调 onTransitionEnd: ()=>{ console.log('导航栏切换结束'); }, // 回调 }); AppRegistry.registerComponent('MyFirstProject', () => MyFirstProject);
先说明下流程第一个界面HomeScreen跳转到第二个界面ChatScreen,然后可以返回到第一界面,在这里想要说的有两个重点:(1) title:`Chat with${navigation.state.params.user}` 注意“`”不是单引号,是和“~”在同一个按键的字符。(2)从第一个界面到第二界面参数是如何传递过去的,看下面的分析:
在HomeScreen界面中,通过const { navigate } =this.props.navigation 获取对象 navigate,那么navigate是个什么东西?来看下打印结果:
function navigate(routeName, params, action) { return navigation.dispatch(_NavigationActions2.default.navigate({ routeName: routeName, params: params, action: action }));
不用意外navigate就是一个函数对象,参数一:需要跳转的界面(是在StackNavigator{}中声明的导航界面【例chat】),参数二:需要传递的数据(例{ user:'Lucy' }),参数三:处理数据或跳转的action (在这里先不管他)。
因此在下面我们使用到了:()=> navigate('Chat', { user:'Lucy' }) 跳转到ChatSrceen界面,并把{ user: 'Lucy' }传递过去。
我们再来看看ChatSrceen是如果接受数据的,在ChatScreen中通过
const { params } =this.props.navigation.state获取数据,打印下params是?结果:{ user: 'Lucy' },
那么this.props.navigation.state 中为什么会存在对象{ user: 'Lucy' },那么我们再打印下this.props.navigation,结果:
好吧,在这里this.props.navigation 变成了一个真正的对象了,而不是函数了,可以看到这个对象中有个属性state,且属性state也是个对象,那么它的内容呢?如下:
很显然对象state中又有对象params,而params就是我们要找的数据{ user: 'Lucy' }。这也是数据传递的过程,至于为什么在HomeScreen中this.propes.navigation是个函数,而到了ChatScreen变成了真正的对象(我们需要的)了,其实上面是把this.props.navigation.navigate 赋值了给{ navigate }。
下面是总的打印结果(方便对比):