ReactNative开发——Navigation的使用
React Native 0.43之前 ‘react-native’包里面,但0.43之后了’rea移除了rect-native’。网上的大部分资料,也是ReactNative 0.43之前的 Navigator的用法,然而我用的0.44版本在开发,这就….
参考: http://facebook.github.io/react-native/docs/navigation.html
安装 ‘react-navigator’依赖
于是我按着文档 https://reactnavigation.org/docs/intro/ 来安装:
在项目目录下执行命令安装:
npm install --save react-navigator
结果呵呵哒:
E:\hybrid\react_native_pro\Project02>npm install
npm WARN peerDependencies The peer dependency react@* included from react-navigation will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-drawer-layout-polyfill will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm WARN peerDependencies The peer dependency react@* included from react-native-tab-view will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.
npm ERR! install trying to install 15.5.4 to E:\hybrid\react_native_pro\Project02\node_modules\react-navigation\node_modules\react
npm ERR! install but already installed versions [ '15.5.4' ]
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "D:\\Program Files\\nodejs\\node.exe" "C:\\Users\\Administrator\\AppData\\Roaming\\npm\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v4.4.7
npm ERR! npm v2.15.12
npm ERR! code EPEERINVALID
npm ERR! peerinvalid The package react@16.0.0-alpha.6 does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer react-native@0.44.0 wants react@16.0.0-alpha.6
npm ERR! peerinvalid Peer react-navigation@1.0.0-beta.11 wants react@*
npm ERR! peerinvalid Peer react-test-renderer@16.0.0-alpha.6 wants react@^16.0.0-alpha.6
npm ERR! Please include the following file with any support request:
npm ERR! E:\hybrid\react_native_pro\Project02\npm-debug.log```
最后我的解决办法是 安装npm3:
npm install -g npm@3
然后重新执行上面的命令安装。
开始学习
HelloWorld
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */
'user react'
import React,{Component} from 'react';
import {AppRegistry,View,Button,Text} from 'react-native';
import {StackNavigator} from 'react-navigation'
/** * 主页面 */
class HomeScreen extends Component {
static navigationOptions = {
/*设置标题*/
title: 'Welcome'
}
render() {
const {navigate} = this.props.navigation;
return (
<View> <Text> Hello,Navigator</Text> <Button title="Chat With Lucy" //跳转第二个页面,第二个参数,向第二个页面传入参数{user:'Lucy'} onPress={() => navigate('Chat',{user: 'Lucy'})} > </Button> </View> ); } } /** * 第二个页面 */ class ChatScreen extends Component { /*可以定义一个函数来读取上个页面传过来的参数*/ static navigationOptions = (({navigation}) => ({ title: `Chat with ${navigation.state.params.user}` })) render() { const { params } = this.props.navigation.state; return ( <View> <Text> Hello,{params.user}</Text> </View> ); } } const Project02 = StackNavigator({ Home: {screen: HomeScreen},Chat: {screen: ChatScreen},}); AppRegistry.registerComponent('Project02',() => Project02);
该代码实现了:
1.定义了2个页面 HomeScreen和ChartScreen。在HomeScreen中有个按钮,点击跳转到到第二个页面并传参。
Navigators
介绍
Navigators是用来定义为你应用顶用导航架构用的,你也可以通过配置让它为您渲染公共的元素,比如头部或者TabBar。
用来构建Navigator的函数
- StackNavigator —— 用来提供类似“栈”的那张导航,比如启动一个页面,这个新的页面覆盖在旧的页面上,继续按返回键这个新的页面将“弹出”又出现旧的页面。
- TabNavigator —— 提供一个TabBar让用户在几个页面之前切换,这种类似:以Android为例,效果等于TabLayout+ViewPager+Fragment那种。
- DrawerNavigator ——提供一个抽屉,左滑出现。
使用Navigators
使用Navigators我们主要学习2个属性,下文Screen指的是我们的页面组件(即上文,HelloWorld中的HomeScreen,和ChildScreen等)
* Screen navigation prop ,我们可以使用它来调用导航操作,比如启动另一个页面。
* Screen navigationOptions,我们可以用来定义navigator的显示属性,比如(title,tab label等)
在顶层组件使用导航
上面一个条目,我们讲到用 screen 的 navigation prop可以进行导航操作,但如果我们要在外部操作导航怎么办呢?
我们可以这样:声明一个Navigators的引用,我们可以使用这个引用进行操作,例如:
const AppNavigator = StackNavigator(SomeAppRouteConfigs);
class App extends React.Component {
someEvent() {
// call navigate for AppNavigator here:
this.navigator && this.navigator.dispatch({ type: 'Navigate',routeName,params });
}
render() {
return (
<AppNavigator ref={nav => { this.navigator = nav; }} /> ); } }
注意,这种解决方案应该只用在最顶层的navigator。
Navigation 容器
当navigation prop没有设置的时候,这个Navigation会自动显示在顶层,她将是一个透明的容器。
当渲染navigaor的时候,这个navigation props 是可选的,如果不设置,它也会有一些默认的操作,比如可以处理URL,外部链接、android会返回键等。这是因为这些系统自带的navigator(StackNavigator、TabNavigator)他们内部使用了createNavigationContainer
方法,通常,这个方法被用来设置 navigator prop 去支持一些函数。
顶部Navigators接受以下属性:
onNavigationStateChange(prevState,newState,action)
这个用来获得Navigation的状态,它可以接收前一个状态,和最新的状态,以及操作
uriPrefix
用来设置url的前缀,表示那些url可以被我们的app处理。
下面,我贴一个例子,来演示以下 uriPrefix
和onNavigationStateChange(prevState,action)
的用法
/** * Created by Administrator on 5/27/2017. */
import React from 'react';
import {
AppRegistry,Text,} from 'react-native';
import {TabNavigator,StackNavigator} from 'react-navigation';
class RecentChatsScreen extends React.Component {
render() {
return <Text>List of recent chats</Text> } } class AllContactsScreen extends React.Component { render() { return ( <View> <Text>Hello,Chat App!</Text> <Button onPress={() => this.props.navigation.navigate('Chat',{user: 'Lucy'})} title="Chat with Lucy" /> </View> ); } } class ChatScreen extends React.Component { static navigationOptions = ({navigation}) => { const {state,setParams} = navigation; const isInfo = state.params.mode === 'info'; const {user} = state.params; return { title: isInfo ? `${user}'s Contact Info` : `Chat with ${user}`,headerRight: (<Button title={isInfo ? 'Done' : `${user}'s Info`} onPress={() => setParams({mode: isInfo ? 'none' : 'info'})} />) }; }; render() { const {params} = this.props.navigation.state; return ( <View> <Text>Chat with {params.user}</Text> </View> ); } } const MainScreenNavigator = TabNavigator({ Recent: { screen: RecentChatsScreen },All: { screen: AllContactsScreen,},}); // MainScreenNavigator.navigationOptions = {title: "Main"}; const SimpleApp = StackNavigator({ // 使用 header:null 去掉StackNavigator的导航栏头部 Home: {screen: MainScreenNavigator,navigationOptions: ({navigation}) => ({header: null}),Chat: { screen: ChatScreen,//路径,user为可以接受的参数 path: 'chat1/:user',} }) const MainApp = () => <SimpleApp //设置 URL's Schema,和 Host uriPrefix={'chat://chat/'} onNavigationStateChange={(preState, newState,action) => { console.log('preState:' + JSON.stringify(preState) + ',newState:' + JSON.stringify(newState) + ',action:' + JSON.stringify(action)); }}/> AppRegistry.registerComponent('Project05',() => MainApp);
上述代码设置了 uriPrefix
为 ‘chat://chat/,并设置了 ChatScreen中的 path为:
chat1/:user, 其中
:user`表示接受参数 user
那么我们可以使用外部的URL来启动这个页面,
我们以Android为例,还需要在AndroidMainifest.xml中的Activity添加一下Intent-Filter。
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"></category>
<data android:scheme="chat" android:host="chat"></data>
</intent-filter>
安装成功之后,我们在命令行输入:adb shell am start -W -a android.intent.action.VIEW -d "chat://chat/chat1/blueberry"
就可跳转到ChatScreen那个页面了,并传入了参数为blueberry
。
相关的ios也可以用外部URL访问本应用的页面,可以参考:https://reactnavigation.org/docs/guides/linking
StackNavigator
StackNavigator用来解决屏幕跳转,用它的效果页面导航效果|类似于栈,新启动的页面覆盖在原先的页面上。
使用
/** * Created by blueberry on 6/15/2017. */
import React,{Component} from 'react';
import {StyleSheet,AppRegistry} from 'react-native';
import {StackNavigator} from 'react-navigation';
class MainScreen extends Component {
static navigationOptions = {
title: 'Home',}
render() {
return (
<View style={{justifyContent: 'center',alignItems: 'center'}}> <Text>{this.props.navigation.state.params.content || ''}</Text> <Button title="Go to Profile" onPress={() => this.props.navigation.navigate('Profile',{ title: 'blueberryTitle',content: 'blueberryContent' })}/> </View> ); } } class Profile extends Component { static navigationOptions = ({navigation}) => ( { title: navigation.state.params.title,}) render() { return ( <View> <Text>{this.props.navigation.state.params.content}</Text> </View> ); } } const App = StackNavigator( /** * 路由配置 */ { Home: {screen: MainScreen},Profile: {screen: Profile,navigationOptions: {headerRight: null}},/** * StackNavigator配置,也可以省略。 */ { // 配置初始化路由名称 initialRouteName: 'Home',// 配置初始化路由的参数 initialRouteParams: {content: '初始化传入的参数'},// 配置默认的 navigationOptions navigationOptions: {headerRight: <Text>右边Header</Text>},// 转场动画开始的回到 onTransitionStart: () => { console.log('start') },} ); AppRegistry.registerComponent('Project05',() => App);
API 定义
StackNavigator(RouteConfigs,StackNavigatorConfig)
这个函数接受2个参数,RouteConfigs和StackNavigatorConfig,其中StatckNavigatorConfig
可以省略,如果省略,则默认选择RouteConfigs
中定义的第一个路由。
RoutConfigs
这个路由配置类,是一个Map结构,key是路由的明城,value 是路由的配置。
StackNavigator(
{ // 以下定义了一个路由,Profile为路由的名称,对应的值则是路由的配置
Profile: {
// `ProfileScreen` 是一个 React UI组件的定义,它就是这个路由的界面
screen: ProfileScreen,// 当 `ProfileScreen` 被StackNavigator加载之后,他将会有一个`navigation` 属性。
// 这个是一个可选项,如果想让这个界面可以被外部链接启动,可以设置这个,:name是用来传入参数的,这个上文讲过。
path: 'people/:name',// 设置这个可以覆盖我们在React Component中设置的navigationOptions属性
navigationOptions: ({navigation}) => ({
title: `${navigation.state.params.name}'s Profile'`,}),...MyOtherRoutes,});
StackNavigatorConfig
属性 | 作用 |
---|---|
initialRouteName | 设置初始化路由名称 |
initialRouteParams | 设置初始化路由的参数 |
navigationOptions | 设置默认的 navigationOptions (这个参数下文将要介绍) |
paths | map结构,覆盖在路由配置中的path |
mode | 定义渲染的和跳转动画的风格,可以设置为card,modal。默认为card。modal可以使界面跳转的而动画是从底部逐渐显示到整个屏幕,这个只对ios有效,因为android,默认转场动画就是从底部逐渐显示到真个屏幕 |
headerMode | 指定如何渲染头部,可以设置为float,screen,none。如果设置为none,则不会有头部;如果设置为float,页面跳转时,header是一直在顶部,而且如果header变化了的话,会有动画,有点像android的共享动画;设置成screen的话,头部是跟随这新的页面重新出现。 |
cardStyle | 可以给页面设置style |
transitionConfig | 一个函数类型,可以用来配置转厂动画 |
onTransitionStart | 函数类型,动画开始后的回调 |
onTransitionEnd | 函数类型,动画结束时的回调 |
Screen Navigation Options
属性 | 作用 |
---|---|
title | string类型,如果设置了它,如果headerTitle或tabBarBabel没有设置的话,将默认会使用这个值 |
header | React Eelement或 是一个参数是HeaderProps返回Rect Element类型的函数类型。它用来显示为header,设置null的话,可以隐藏header |
headerTitle | string 或者 React Element类型,用来设置header,默认显示的 title |
headerBackTitle | string 类型,用来设置在ios上显示黑色按钮,设置null不显示,默认是title |
headerTruncatedBackTitle | string 类型, 用来设置黑色按钮,当headerBackTitle 没有充满屏幕的时候。 |
headerRight | React Element类型,用来在Header右边添加控件 |
headerLeft | React Element类型,用来在Header左边添加控件 |
headerStyle | 设置header的样式 |
headerTitleStyle | 用来设置title组件的样式 |
headerBackTitleStyle | 用来设置黑色Title的样式 |
headerTintColor | 用来设置header的颜色 |
headerPressColorAndroid | 用来设置涟漪效果的颜色,android>5.0有效 |
gesturesEnabled | 开启的话,你可以用手势 关闭页面,ios默认是true,Android默认是false。我用android机开启该选项,不知道用手势什么关~~。这TM就尴尬了~ |
Navigator Props
我们创建StackNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给StackNavigator传入该属性,这个属性将继续传递StackNavigator中的screens,例如:
const SomeStack = StackNavigator({
// config
});
<SomeStack screenProps={/* 这个属性将传递给屏幕组件,在屏幕组件使用 this.props.screenProps就可以访问 */} />
注意这个键一定要是 screenProps,别的可不行哟。
TabNavigator
用这个可以实现几个屏幕之间相互切换,(类似于android原生,TabLayout+Fragment 页面切换那种效果)。
使用
/** * Created by blueberry on 6/15/2017. */
import React,AppRegistry,Image,TabBarBottom,TabView,TabBarTop} from 'react-navigation';
class HomeScreen extends Component {
static navigationOptions = {
tabBarLabel: 'Home',tabBarIcon: ({tintColor}) => (<Image source={require('./img/chat_online_talk.png')} style={[styles.icon, {tintColor: tintColor}]} />),}; render() { return ( <Button title="Go to Notification" onPress={() => this.props.navigation.navigate('Notifications')}/> ); } } class NotificationScreen extends Component { static navigationOptions = { tabBarLabel: 'Notifications',tabBarIcon: ({tintColor}) => (<Image source={require('./img/notification.png')} style={[styles.icon,// 也可以是其他React Element,// tabBarIcon: ({tintColor}) => (<Button title="按钮" onPress={() => { // }}/>),} ; render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); } } var styles = StyleSheet.create({ icon: {width: 26,height: 26} }); const App = TabNavigator( { Home: {screen: HomeScreen},Notifications: {screen: NotificationScreen} },{ tabBarOptions: { //激活的tab tint颜色 activeTintColor: '#e91e63',//没有激活的tab tint颜色 inactiveTintColor: 'black',//大写转换 upperCaseLabel: true,//显示icon showIcon: true,// android默认是TabBarTop,ios默认是TabBarBottom,tabBarComponent: TabBarBottom,// 可以为 top,bottom,用来决定TabBar放置的位置 tabBarPosition: 'bottom',//设置是否可以滑动 swipeEnabled: true,//切换时是否欧动画效果 animationEnabled: false,// 是否懒渲染tabs lazy: false,//第一个被加载的路由名称 initialRouteName: 'Home',//路由名称数组 order: ['Home','Notifications'],paths: {Home: 'home',Notifications: 'Notifications'},backBehavior: true,() => App);
Api 定义
TabNavigator(RouteConfigs,TabNavigatorConfigs)
RouteConfigs
这个和StackNavigator的RouteConfigs一样,上文已经讲过,用来设置路由信息。
TabNavigatorConfig
属性 | 作用 |
---|---|
tabBarComponent | 用来设置tab bar的组件,ios默认是TabBarBottom,android默认是TabBarTop |
tabBarPosition | 用来设置tabBar的位置,可以为 ‘top’ 或者’bottom’ |
swipeEnable | 用来设置是否可以滑动切换 |
animateEnable | 用来设置是否有动画效果 |
lazy | 用来设置是否“懒渲染”tabbar |
tabBarOption | 用来设置tabBar的一些属性,颜色、样式等等,下文将要介绍 |
initialRouteName | 初始化路由的名称 |
order | 路由名称数组 |
paths | 提供一个map,可以路由对应的path |
backBehavior | 如果设置为true,那么上面的例子,在第二个页面,按返回将不能反会到前一个页面,也就是是this.props.navigation.goBack()’不会起作用 |
TabBarBottom 的 tabBarOptions 设置
属性 | 作用 |
---|---|
activeTintColor | 激活的tab的tint 颜色,tint颜色值,icon和Label的颜色 |
activeBackgroundColor | 激活tab的背景颜色 |
inactiveTintColor | 没被激活的tint颜色 |
inactiveBackgroundColor | 没被激活的tab的背景色 |
showLabel | 是否显示label,默认是true |
style | tab bar的样式 |
labelStyle | label的样式 |
tabStyle | tab的样式 |
TabBarTop 的 tabBarOptions设置
属性 | 作用 |
---|---|
activeTintColor | 激活的tab的tint 颜色,tint颜色值,icon和Label的颜色 |
inactiveTintColor | 没被激活的tint颜色 |
showIcon | 是否显示icon,默认是false |
showLabel | 是否显示label,默认是true |
upperCaseLabel | 是够开启大写转换,默认是true |
pressColor | 按压颜色,涟漪效果,andorid>5.0有效 |
pressOpacity | 按压颜色,透明度变换,android<5.0 和ios可用。 |
scrollEnabled | tabs是够可以滑动 |
tabStyle | tab的样式 |
indicatorStyle | 底部指示器的样式 |
labelStyle | label的样式 |
iconStyle | icon的样式 |
style | tab bar的样式 |
举个栗子:
tabBarOptions: {
labelStyle: {
fontSize: 12,tabStyle: {
width: 100,style: {
backgroundColor: 'blue',}
Screen Navigation Options
属性 | 作用 |
---|---|
title | 标题,如果headerTitle,和tabBarLabel,不设置的话,就默认是title |
tabBarVisible | 决定隐藏还是显示tab bar |
tabBarIcon | 可以是一个React Eclement,或者是一个参数为{focused:boolean,tintColor:string} 返回Rect Element的函数,用来显示在Tab Bar上 |
tabBarLabel | string类型,或者React Element类型,或者是参数为{focused:boolean,tintColor:string} 返回React Element的函数 |
Navigator Props
我们创建TabNavigator的时候,如果想从外部给屏幕组件传入扩展的属性,可以使用
* screenProps 给TabNavigator传入该属性,这个属性将继续传递TabNavigator中的screens。这个和StackNavigator的用法一样,可以参考上文。
DrawerNavigator
使用
/** * Created by blueberry on 6/15/2017. */
import React,StyleSheet,ScrollView} from 'react-native';
import {DrawerNavigator,DrawerItems} from 'react-navigation';
class HomeScreen extends Component {
static navigationOptions = {
drawerLabel: 'Home',drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/chat_online_talk.png')}/>),} render() { return ( <View> <Button title="Go to notifications" onPress={() => this.props.navigation.navigate('Notifications')}/> <Button title="打开抽屉" onPress={() => this.props.navigation.navigate('DrawerOpen')}/> <Button title="关闭抽屉" onPress={() => this.props.navigation.navigate('DrawerClose')}/> </View> ); } } class NotificationScreen extends Component { static navigationOptions = { drawerLabel: 'notifications',drawerIcon: ({tintColor}) => (<Image style={[styles.icon, {tintColor: tintColor}]} source={require('./img/notification.png')}/>),} render() { return ( <Button title="Go back home" onPress={() => this.props.navigation.goBack()}/> ); } } const App = DrawerNavigator( {Home: {screen: HomeScreen},Notifications: {screen: NotificationScreen}},//一下是DrawerNavigator 的配置 { // 设置宽度 drawerWidth: 300,// 设置从右边拉出,还是左边拉出 drawerPosition: 'left',//默认的的值是 DrawerItems,我们也可以自己配置组件 contentComponent: props => <ScrollView style={{borderWidth: 1,borderColor: 'red'}}><DrawerItems {...props}/></ScrollView>,contentOptions: { items: ['Home','Notification'],activeItemKey: 'key',activeTintColor: '#ff863f',activeBackgroundColor: '#d0caff',inactiveTintColor: '#000000',inactiveBackgroundColor: '#fffcf8',//这个设置了没起作用,android,api 0.45 onItemPress: (route) => { console.log('TAG' + JSON.stringify(route)) },style: null,labelStyle: null,// initialRouteName:'Notifications',} ) ; var styles = StyleSheet.create({ icon: {width: 26,height: 26} }); AppRegistry.registerComponent('Project05',() => App);
可以使用一下操作,打开或关闭抽屉
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
Api定义
DrawerNavigator(RouteConfigs,DrawerNavigatorConfig)
RouteConfigs
这个和StackNavigator一样,可以参考上文。
DrawerNavigatorConfig
属性 | 作用 |
---|---|
drawerWidth | 抽屉的宽度 |
drawerPosition | 枚举值可以为‘left’或’rigt’表示抽屉是在左边还是右边 |
contentComponent | 可以自定义显示drawer item的组件,默认是实现是DrawerItem |
contentOptions | drawer 内容的一些设置,背景颜色,tint颜色等等,下文将会讲到 |
DrawerItems 的contentOptions
属性 | 作用 |
---|---|
items | 路由的数组 |
activeItemKey | 正在活动的路由的key |
activeTintColor | 正在活动的 item tint 颜色 |
activeBackgroundColor | 正在活动的item的 背景颜色 |
inactiveTintColor | 不在活动的item的 tint颜色 |
inactiveBackgroundColor | 不在活动的item 的背景颜色 |
onItemPress(route) | 设置一个函数,item被按下时,这个函数将被调用 |
style | Dawer的样式 |
labelStyle | label的样式 |
Screen Navigation Options
属性 | 作用 |
---|---|
title | 标题,如果headerTitle,tintColor:string}返回React Element的函数 |
Navigator Props
这个跟StackNavigator 和 TabNavigator的方式一样,可以参考上文。
Screen中的 Navigation 属性
每个Screen都会接收这样一个属性,它其中包含了以下对象:
- navigate 用来跳转到其它页面。
- state 屏幕当前的 state/routes 里面包含有路由信息和参数信息。
- setParams 可以用来改变参数信息。
- goBack 用来关闭当前的活动页面,并返回。
dispatch 给路由发送一个action。
下面来逐个讲解喽~
navigate
它的函数形式为:
navigate(routeName,params,action)
- routeName 要跳转的页面路由名称。
- params 参数信息。
- action 高级用法~,逐个子 action运行在child路由,如果要跳转的页面也是一个Navigator的话。
state
页面可以通过 this.props.navigation.state
获得,它的形式为:
{
// 路由的名称
routeName: 'profile',//唯一的id
key: 'main0',// 参数
params: { hello: 'world' }
}
setParams
改变路由的参数
例如:
class ProfileScreen extends React.Component {
render() {
const {setParams} = this.props.navigation;
return (
<Button onPress={() => setParams({name: 'Lucy'})} title="Set title name to 'Lucy'" /> ) } }
goBack
示例:
class HomeScreen extends React.Component {
render() {
const {goBack} = this.props.navigation;
return (
<View> <Button onPress={() => goBack()} title="Go back from this HomeScreen" /> <Button onPress={() => goBack(null)} title="Go back anywhere" /> <Button onPress={() => goBack('screen-123')} title="Go back from screen-123" /> </View> ) } }
dispatch
给路由发送一个action。用个栗子(没有什么比看代码来的简单明了了)。
/** * Created by blueberry on 6/15/2017. */
import React,Text} from 'react-native';
import {NavigationActions,TabNavigator} from 'react-navigation';
class MainScreen extends Component {
render() {
return (
<View> <Button title="跳转到Child页面" onPress={() => this.props.navigation.navigate('Child')}/> <Text>{this.props.navigation.state.params ? this.props.navigation.state.params.title : ''}</Text> </View> ); } } class ChildScreen extends Component { render() { const navigationActions = NavigationActions.navigate({ routeName: 'Home',params: {title: 'blueberryTitle'} }); return ( <View> <Button title="返回" onPress={() => this.props.navigation.goBack()}/> <Button title="返回Home显示title" onPress={() => this.props.navigation.dispatch(navigationActions)}/> </View> ); } } const App = TabNavigator( {Home: {screen: MainScreen,Child: {screen: ChildScreen}} ); AppRegistry.registerComponent('NavigationUsage',() => App);
上面核心代码:
const navigationActions = NavigationActions.navigate({
routeName: 'Home',params: {title: 'blueberryTitle'}
});
this.props.navigation.dispatch(navigationActions)
NavigationActions创建了一个acionts,然后使用dispatch去执行了,上面的执行效果就是,挑战到了Home页面,并传入了参数{title:'blueberryTitle'}
。
Naviation Actions
上文已经简单延时了navigation.dispatch()
的用法。
它支持的action有:
- navigate 跳转到其他路由
- Rest 使用一个新的State替换当前的state。
- Back 返回到前一个状态
- Set Params 给你个路由设置 参数。
- Init 如果state没有定义,使用它初始化第一个状态。
Navigate
用法:
import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',params: {},action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
属性 | 作用 |
---|---|
routeName | 路由名称 |
params | 参数 |
action | 高级用法,如果他要跳转的路由也是一个Navigator,用可以用来设置那个Navigator的action |
Reset
用来重新设置路由记录
const resetAction = NavigationActions.reset({
index: 1,actions: [
NavigationActions.navigate({ routeName: 'Profile'}),NavigationActions.navigate({ routeName: 'Settings'})
]
})
this.props.navigation.dispatch(resetAction
注意 index的值 必须在0 - actions.lenght的范围内,不能越界,指定当前在栈中的位置。
Back
使用方法:
const backAction = NavigationActions.back({
key: 'Profile'
})
this.props.navigation.dispatch(backAction)
key为路由的唯一身份,但是我设置了以后,使用this.props.navigation.dispatch()
没有效果,不设置的话,可以返回,我使用的Andorid机测试。
SetParams
const setParamsAction = NavigationActions.setParams({
params: { title: 'Hello' },key: 'screen-123',})
this.props.navigation.dispatch(setParamsAction)
- parmas 为参数
- key 为要修改的路由的身份
Screen Navigation Options
配置navigatinOptions
可以用2中方法来设置 navigationOptions
静态配置
示例:
class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',};
...
动态配置
示例:
class ProfileScreen extends React.Component {
static navigationOptions = ({ navigation,screenProps }) => ({
title: navigation.state.params.name + "'s Profile!",headerRight: <Button color={screenProps.tintColor} {...} />,});
这个函数接收的参数为props,props参数中包含 navigation,screenProps,navigationOptions。返回值用来决定设置的navigationOpiotns。
参数的结构如下:
+ Props
- navigation
- screenProps
- navigationOptions
一般的Navigation Options 配置方法
class MyScreen extends React.Component {
static navigationOptions = {
title: 'Great',};
...
其他的配置方法
可以在配置路由的时候设置:
const SimpleApp = StackNavigator({
// 使用 header:null 去掉StackNavigator的导航栏头部
Home: {screen: MainScreenNavigator,navigationOptions: ({navigation}) => ({header: null}),Chat: {
screen: ChatScreen,//路径,user为可以接受的参数
path: 'chat1/:user',}
},{})
还可以在Navigation 配置中设置
const App = StackNavigator(
/** * 路由配置 */
{
Home: {screen: MainScreen},navigationOptions: {headerRight: null}},/** * StackNavigator配置,也可以省略。 */
{
navigationOptions: {headerRight: <Text>右边Header</Text>},} );
示例代码地址
https://github.com/blueberryCoder/RNDemo/tree/master/NavigationUsage