react-native新导航组件react-navigation详解

有问题找 issues, 基本上坑都在这里.

官方文档

主要构成

按使用形式主要分三部分:

StackNavigator: 类似于普通的Navigator,屏幕上方导航栏
TabNavigator: 相当于iOS里面的TabBarController,屏幕下方的标签栏
DrawerNavigator: 抽屉效果,侧边滑出

StackNavigator 导航栏

API: StackNavigator(RouteConfigs, StackNavigatorConfig)


   
   
  1. // 注册导航
  2. const Navs = StackNavigator({
  3. Home: { screen: Tabs },
  4. HomeTwo: {
  5. screen: HomeTwo, // 必须, 其他都是非必须
  6. path:'app/homeTwo', 使用url导航时用到, 如 web app 和 Deep Linking
  7. navigationOptions: {} // 此处设置了, 会覆盖组件内的`static navigationOptions`设置. 具体参数详见下文
  8. },
  9. HomeThree: { screen: HomeThree },
  10. HomeFour: { screen: HomeFour }
  11. }, {
  12. initialRouteName: 'Home', // 默认显示界面
  13. navigationOptions: { // 屏幕导航的默认选项, 也可以在组件内用 static navigationOptions 设置(会覆盖此处的设置)
  14. header: { // 导航栏相关设置项
  15. backTitle: '返回', // 左上角返回键文字
  16. style: {
  17. backgroundColor: '#fff'
  18. },
  19. titleStyle: {
  20. color: 'green'
  21. }
  22. },
  23. cardStack: {
  24. gesturesEnabled: true
  25. }
  26. },
  27. mode: 'card', // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果)
  28. headerMode: 'screen', // 导航栏的显示模式, screen: 有渐变透明效果, float: 无透明效果, none: 隐藏导航栏
  29. onTransitionStart: ()=>{ console.log('导航栏切换开始'); }, // 回调
  30. onTransitionEnd: ()=>{ console.log('导航栏切换结束'); } // 回调
  31. });

navigationOptions

参数:

  • title: 导航栏的标题

  • header: 导航栏设置对象

    • visible: 导航栏是否显示
    • title: 导航栏的标题, 可以是字符串也可以是个组件
    • backTitle: 左上角的返回键文字, 默认是上一个页面的title
    • right: 导航栏右按钮
    • left: 导航栏左按钮
    • style: 导航栏的style
    • titleStyle: 导航栏的title的style
    • tintColor: 导航栏颜色
  • cardStack: 配置card stack

    • gesturesEnabled: 是否允许右滑返回,在iOS上默认为true,在Android上默认为false

在组件中设置static navigationOptions示例:


   
   
  1. static navigationOptions = {
  2. title: 'homeThree',
  3. header: (navigation, defaultHeader) => ({
  4. ...defaultHeader, // 默认预设
  5. visible: true // 覆盖预设中的此项
  6. }),
  7. cardStack: {
  8. gesturesEnabled: false // 是否可以右滑返回
  9. }
  10. };
  11. // 或这样
  12. static navigationOptions = {
  13. // title: 'Two', // 写死标题
  14. title: (navigation, childRouter) => { // 动态标题
  15. if (navigation.state.params.isSelected) {
  16. return `${navigation.state.params.name}选中`;
  17. } else {
  18. return `${navigation.state.params.name}没选中`;
  19. }
  20. },
  21. header: ({ state, setParams, goBack }) => {
  22. let right;
  23. if (state.params.isSelected) {
  24. right = (<Button title="取消" onPress={() => setParams({ isSelected: false })}/>);
  25. } else {
  26. right = (<Button title="选择" onPress={() => setParams({ isSelected: true })}/>);
  27. }
  28. let left = (<Button title="返回" onPress={() => goBack()}/>);
  29. let visible = false; // 是否显示导航栏
  30. return { right, left, visible };
  31. },
  32. // header: {left: <Button title="返回"/>},
  33. };

StackNavigatorConfig

参数:

  • initialRouteName: 设置默认的页面组件,必须是上面已注册的页面组件
  • initialRouteParams: 初始路由的参数
  • navigationOptions: 屏幕导航的默认选项
  • paths: RouteConfigs里面路径设置的映射

  • mode: 页面切换模式:

    • card: 普通app常用的左右切换
    • modal: 上下切换
  • headerMode: 导航栏的显示模式:

    • float: 无透明效果, 默认
    • screen: 有渐变透明效果, 如微信QQ的一样
    • none: 隐藏导航栏
  • cardStyle: 样式

  • onTransitionStart: 页面切换开始时的回调函数

  • onTransitionEnd: 页面切换结束时的回调函数

TabNavigator 标签栏


   
   
  1. // 注册tabs
  2. const Tabs = TabNavigator({
  3. Home: {
  4. screen: Home,
  5. navigationOptions: { // 也可以写在组件的static navigationOptions内
  6. tabBar: {
  7. label: '首页',
  8. icon: ({tintColor}) => (<Image source={ require( './app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  9. },
  10. }
  11. },
  12. Bill: {
  13. screen: Bill,
  14. navigationOptions: {
  15. tabBar: {
  16. label: '账单',
  17. icon: ({tintColor}) => (<Image source={ require( './app/images/bill.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  18. },
  19. }
  20. },
  21. Me: {
  22. screen: Me,
  23. navigationOptions: {
  24. tabBar: {
  25. label: '我',
  26. icon: ({tintColor}) => (<Image source={ require( './app/images/me.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  27. },
  28. }
  29. }
  30. }, {
  31. animationEnabled: false, // 切换页面时是否有动画效果
  32. tabBarPosition: 'bottom', // 显示在底端,android 默认是显示在页面顶端的
  33. swipeEnabled: false, // 是否可以左右滑动切换tab
  34. backBehavior: 'none', // 按 back 键是否跳转到第一个Tab(首页), none 为不跳转
  35. tabBarOptions: {
  36. activeTintColor: '#ff8500', // 文字和图片选中颜色
  37. inactiveTintColor: '#999', // 文字和图片未选中颜色
  38. showIcon: true, // android 默认不显示 icon, 需要设置为 true 才会显示
  39. indicatorStyle: {
  40. height: 0 // 如TabBar下面显示有一条线,可以设高度为 0 后隐藏
  41. },
  42. style: {
  43. backgroundColor: '#fff', // TabBar 背景色
  44. // height: 44
  45. },
  46. labelStyle: {
  47. fontSize: 10, // 文字大小
  48. },
  49. },
  50. });

DrawerNavigator抽屉


   
   
  1. const DrawerNav = DrawerNavigator({
  2. Home: { screen: Home },
  3. Bill: { screen: Bill },
  4. Me: { screen: Me },
  5. HomeTwo: { screen: HomeTwo },
  6. HomeThree: { screen: HomeThree },
  7. HomeFour: { screen: HomeFour },
  8. BillTwo: { screen: BillTwo },
  9. BillThree: { screen: BillThree }
  10. }, {
  11. drawerWidth: 200, // 抽屉宽
  12. drawerPosition: 'left', // 抽屉在左边还是右边
  13. // contentComponent: CustomDrawerContentComponent, // 自定义抽屉组件
  14. contentOptions: {
  15. initialRouteName: Home, // 默认页面组件
  16. activeTintColor: 'white', // 选中文字颜色
  17. activeBackgroundColor: '#ff8500', // 选中背景颜色
  18. inactiveTintColor: '#666', // 未选中文字颜色
  19. inactiveBackgroundColor: '#fff', // 未选中背景颜色
  20. style: { // 样式
  21. }
  22. }
  23. });

navigation

StackNavigator中注册后的组件都有navigation这个属性. navigation又有5个参数:navigategoBackstatesetParamsdispatch, 可以在组件下console.log一下this.props就能看到.

  • this.props.navigation.navigate('Two', { name: 'two' }): push下一个页面

    • routeName: 注册过的目标路由名称
    • params: 传递的参数
    • action: 如果该界面是一个navigator的话,将运行这个sub-action
  • this.props.navigation.goBack(): 返回上一页

  • this.props.navigation.state: 每个界面通过这去访问它的router,state其中包括了:

    • routeName: 路由名
    • key: 路由身份标识
    • params: 参数
  • this.props.navigation.setParams: 该方法允许界面更改router中的参数,可以用来动态的更改导航栏的内容

  • this.props.navigation.dispatch: 可以dispatch一些action,主要支持的action有:

    • Navigate:

      
             
             
      1. import { NavigationActions } from 'react-navigation'
      2. const navigationAction = NavigationActions.navigate({
      3. routeName: 'Profile',
      4. params: {},
      5. // navigate can have a nested navigate action that will be run inside the child router
      6. action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
      7. })
      8. this.props.navigation.dispatch(navigationAction)
    • Reset: Reset方法会清除原来的路由记录,添加上新设置的路由信息, 可以指定多个action,index是指定默认显示的那个路由页面, 注意不要越界了

      
             
             
      1. import { NavigationActions } from 'react-navigation'
      2. const resetAction = NavigationActions.reset({
      3. index: 0,
      4. actions: [
      5. NavigationActions.navigate({ routeName: 'Profile'}),
      6. NavigationActions.navigate({ routeName: 'Two'})
      7. ]
      8. })
      9. this.props.navigation.dispatch(resetAction)
    • SetParams: 为指定的router更新参数,该参数必须是已经存在于router的param中

      
             
             
      1. import { NavigationActions } from 'react-navigation'
      2. const setParamsAction = NavigationActions.setParams({
      3. params: {}, // these are the new params that will be merged into the existing route params
      4. // The key of the route that should get the new params
      5. key: 'screen-123',
      6. })
      7. this.props.navigation.dispatch(setParamsAction)

Navigation Actions

  • 支持以下actions:
    • Navigate:
    • Reset:
    • Back:
    • Set Params:
    • Init:

Deep Link

其他app或浏览器使用url打开次app并进入指定页面. 如浏览器输入url demo4://home/home3直接进入home3页面.

iOS版设置

  1. 使用Xcode设置Schemes;
  2. AppDelegate添加一下代码:

   
   
  1. - ( BOOL) application:( UIApplication *)application openURL:( NSURL *)url
  2. sourceApplication:( NSString *)sourceApplication annotation:( id)annotation {
  3. return [RCTLinkingManager application:application openURL:url
  4. sourceApplication:sourceApplication annotation:annotation];
  5. }
  1. js组件在注册路由时设置唯一的路径path, 例如Home2: { screen: Home2, path:'app/Home2' };
  2. 在手机浏览器访问demo4://app/Home2, 弹窗选择打开, 就可以打开demo4 app并进到Home2页面了.

有问题找 issues, 基本上坑都在这里.

官方文档

主要构成

按使用形式主要分三部分:

StackNavigator: 类似于普通的Navigator,屏幕上方导航栏
TabNavigator: 相当于iOS里面的TabBarController,屏幕下方的标签栏
DrawerNavigator: 抽屉效果,侧边滑出

StackNavigator 导航栏

API: StackNavigator(RouteConfigs, StackNavigatorConfig)


 
 
  1. // 注册导航
  2. const Navs = StackNavigator({
  3. Home: { screen: Tabs },
  4. HomeTwo: {
  5. screen: HomeTwo, // 必须, 其他都是非必须
  6. path:'app/homeTwo', 使用url导航时用到, 如 web app 和 Deep Linking
  7. navigationOptions: {} // 此处设置了, 会覆盖组件内的`static navigationOptions`设置. 具体参数详见下文
  8. },
  9. HomeThree: { screen: HomeThree },
  10. HomeFour: { screen: HomeFour }
  11. }, {
  12. initialRouteName: 'Home', // 默认显示界面
  13. navigationOptions: { // 屏幕导航的默认选项, 也可以在组件内用 static navigationOptions 设置(会覆盖此处的设置)
  14. header: { // 导航栏相关设置项
  15. backTitle: '返回', // 左上角返回键文字
  16. style: {
  17. backgroundColor: '#fff'
  18. },
  19. titleStyle: {
  20. color: 'green'
  21. }
  22. },
  23. cardStack: {
  24. gesturesEnabled: true
  25. }
  26. },
  27. mode: 'card', // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果)
  28. headerMode: 'screen', // 导航栏的显示模式, screen: 有渐变透明效果, float: 无透明效果, none: 隐藏导航栏
  29. onTransitionStart: ()=>{ console.log('导航栏切换开始'); }, // 回调
  30. onTransitionEnd: ()=>{ console.log('导航栏切换结束'); } // 回调
  31. });

navigationOptions

参数:

  • title: 导航栏的标题

  • header: 导航栏设置对象

    • visible: 导航栏是否显示
    • title: 导航栏的标题, 可以是字符串也可以是个组件
    • backTitle: 左上角的返回键文字, 默认是上一个页面的title
    • right: 导航栏右按钮
    • left: 导航栏左按钮
    • style: 导航栏的style
    • titleStyle: 导航栏的title的style
    • tintColor: 导航栏颜色
  • cardStack: 配置card stack

    • gesturesEnabled: 是否允许右滑返回,在iOS上默认为true,在Android上默认为false

在组件中设置static navigationOptions示例:


 
 
  1. static navigationOptions = {
  2. title: 'homeThree',
  3. header: (navigation, defaultHeader) => ({
  4. ...defaultHeader, // 默认预设
  5. visible: true // 覆盖预设中的此项
  6. }),
  7. cardStack: {
  8. gesturesEnabled: false // 是否可以右滑返回
  9. }
  10. };
  11. // 或这样
  12. static navigationOptions = {
  13. // title: 'Two', // 写死标题
  14. title: (navigation, childRouter) => { // 动态标题
  15. if (navigation.state.params.isSelected) {
  16. return `${navigation.state.params.name}选中`;
  17. } else {
  18. return `${navigation.state.params.name}没选中`;
  19. }
  20. },
  21. header: ({ state, setParams, goBack }) => {
  22. let right;
  23. if (state.params.isSelected) {
  24. right = (<Button title="取消" onPress={() => setParams({ isSelected: false })}/>);
  25. } else {
  26. right = (<Button title="选择" onPress={() => setParams({ isSelected: true })}/>);
  27. }
  28. let left = (<Button title="返回" onPress={() => goBack()}/>);
  29. let visible = false; // 是否显示导航栏
  30. return { right, left, visible };
  31. },
  32. // header: {left: <Button title="返回"/>},
  33. };

StackNavigatorConfig

参数:

  • initialRouteName: 设置默认的页面组件,必须是上面已注册的页面组件
  • initialRouteParams: 初始路由的参数
  • navigationOptions: 屏幕导航的默认选项
  • paths: RouteConfigs里面路径设置的映射

  • mode: 页面切换模式:

    • card: 普通app常用的左右切换
    • modal: 上下切换
  • headerMode: 导航栏的显示模式:

    • float: 无透明效果, 默认
    • screen: 有渐变透明效果, 如微信QQ的一样
    • none: 隐藏导航栏
  • cardStyle: 样式

  • onTransitionStart: 页面切换开始时的回调函数

  • onTransitionEnd: 页面切换结束时的回调函数

TabNavigator 标签栏


 
 
  1. // 注册tabs
  2. const Tabs = TabNavigator({
  3. Home: {
  4. screen: Home,
  5. navigationOptions: { // 也可以写在组件的static navigationOptions内
  6. tabBar: {
  7. label: '首页',
  8. icon: ({tintColor}) => (<Image source={ require( './app/images/home.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  9. },
  10. }
  11. },
  12. Bill: {
  13. screen: Bill,
  14. navigationOptions: {
  15. tabBar: {
  16. label: '账单',
  17. icon: ({tintColor}) => (<Image source={ require( './app/images/bill.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  18. },
  19. }
  20. },
  21. Me: {
  22. screen: Me,
  23. navigationOptions: {
  24. tabBar: {
  25. label: '我',
  26. icon: ({tintColor}) => (<Image source={ require( './app/images/me.png')} style={[{tintColor: tintColor},styles.icon]}/>),
  27. },
  28. }
  29. }
  30. }, {
  31. animationEnabled: false, // 切换页面时是否有动画效果
  32. tabBarPosition: 'bottom', // 显示在底端,android 默认是显示在页面顶端的
  33. swipeEnabled: false, // 是否可以左右滑动切换tab
  34. backBehavior: 'none', // 按 back 键是否跳转到第一个Tab(首页), none 为不跳转
  35. tabBarOptions: {
  36. activeTintColor: '#ff8500', // 文字和图片选中颜色
  37. inactiveTintColor: '#999', // 文字和图片未选中颜色
  38. showIcon: true, // android 默认不显示 icon, 需要设置为 true 才会显示
  39. indicatorStyle: {
  40. height: 0 // 如TabBar下面显示有一条线,可以设高度为 0 后隐藏
  41. },
  42. style: {
  43. backgroundColor: '#fff', // TabBar 背景色
  44. // height: 44
  45. },
  46. labelStyle: {
  47. fontSize: 10, // 文字大小
  48. },
  49. },
  50. });

DrawerNavigator抽屉


 
 
  1. const DrawerNav = DrawerNavigator({
  2. Home: { screen: Home },
  3. Bill: { screen: Bill },
  4. Me: { screen: Me },
  5. HomeTwo: { screen: HomeTwo },
  6. HomeThree: { screen: HomeThree },
  7. HomeFour: { screen: HomeFour },
  8. BillTwo: { screen: BillTwo },
  9. BillThree: { screen: BillThree }
  10. }, {
  11. drawerWidth: 200, // 抽屉宽
  12. drawerPosition: 'left', // 抽屉在左边还是右边
  13. // contentComponent: CustomDrawerContentComponent, // 自定义抽屉组件
  14. contentOptions: {
  15. initialRouteName: Home, // 默认页面组件
  16. activeTintColor: 'white', // 选中文字颜色
  17. activeBackgroundColor: '#ff8500', // 选中背景颜色
  18. inactiveTintColor: '#666', // 未选中文字颜色
  19. inactiveBackgroundColor: '#fff', // 未选中背景颜色
  20. style: { // 样式
  21. }
  22. }
  23. });

navigation

StackNavigator中注册后的组件都有navigation这个属性. navigation又有5个参数:navigategoBackstatesetParamsdispatch, 可以在组件下console.log一下this.props就能看到.

  • this.props.navigation.navigate('Two', { name: 'two' }): push下一个页面

    • routeName: 注册过的目标路由名称
    • params: 传递的参数
    • action: 如果该界面是一个navigator的话,将运行这个sub-action
  • this.props.navigation.goBack(): 返回上一页

  • this.props.navigation.state: 每个界面通过这去访问它的router,state其中包括了:

    • routeName: 路由名
    • key: 路由身份标识
    • params: 参数
  • this.props.navigation.setParams: 该方法允许界面更改router中的参数,可以用来动态的更改导航栏的内容

  • this.props.navigation.dispatch: 可以dispatch一些action,主要支持的action有:

    • Navigate:

      
           
           
      1. import { NavigationActions } from 'react-navigation'
      2. const navigationAction = NavigationActions.navigate({
      3. routeName: 'Profile',
      4. params: {},
      5. // navigate can have a nested navigate action that will be run inside the child router
      6. action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
      7. })
      8. this.props.navigation.dispatch(navigationAction)
    • Reset: Reset方法会清除原来的路由记录,添加上新设置的路由信息, 可以指定多个action,index是指定默认显示的那个路由页面, 注意不要越界了

      
           
           
      1. import { NavigationActions } from 'react-navigation'
      2. const resetAction = NavigationActions.reset({
      3. index: 0,
      4. actions: [
      5. NavigationActions.navigate({ routeName: 'Profile'}),
      6. NavigationActions.navigate({ routeName: 'Two'})
      7. ]
      8. })
      9. this.props.navigation.dispatch(resetAction)
    • SetParams: 为指定的router更新参数,该参数必须是已经存在于router的param中

      
           
           
      1. import { NavigationActions } from 'react-navigation'
      2. const setParamsAction = NavigationActions.setParams({
      3. params: {}, // these are the new params that will be merged into the existing route params
      4. // The key of the route that should get the new params
      5. key: 'screen-123',
      6. })
      7. this.props.navigation.dispatch(setParamsAction)

Navigation Actions

  • 支持以下actions:
    • Navigate:
    • Reset:
    • Back:
    • Set Params:
    • Init:

Deep Link

其他app或浏览器使用url打开次app并进入指定页面. 如浏览器输入url demo4://home/home3直接进入home3页面.

iOS版设置

  1. 使用Xcode设置Schemes;
  2. AppDelegate添加一下代码:

 
 
  1. - ( BOOL) application:( UIApplication *)application openURL:( NSURL *)url
  2. sourceApplication:( NSString *)sourceApplication annotation:( id)annotation {
  3. return [RCTLinkingManager application:application openURL:url
  4. sourceApplication:sourceApplication annotation:annotation];
  5. }
  1. js组件在注册路由时设置唯一的路径path, 例如Home2: { screen: Home2, path:'app/Home2' };
  2. 在手机浏览器访问demo4://app/Home2, 弹窗选择打开, 就可以打开demo4 app并进到Home2页面了.

猜你喜欢

转载自blog.csdn.net/z93701081/article/details/89214828