React Native之react-navigation总结

react-navigation号称拥有近乎原生页面切换的性能,在项目中开始投入使用以来,确实发现了其优越性,一定程度上解决了RN在页面路由管理方面上的薄弱,下面就我在项目中遇到的坑和难点做一个总结。

1、Header的参数设置后无效

  每一个navigator只会查看其直接子级进行配置,比如一个页面在一个stackNavigator里,而这个stackNavigator在一个tabNavigator里,那么直接在页面配置 navigationOptions 是无效的,要在stackNavigator里进行配置,例如:

let HomeStack = createStackNavigator({ A });
let SettingsStack = createStackNavigator({ B });

HomeStack.navigationOptions = {
  tabBarLabel: 'Home!',
};

SettingsStack.navigationOptions = {
  tabBarLabel: 'Settings!',
};

export default createBottomTabNavigator({
  HomeStack,
  SettingsStack,
});

2、react-navigation的Header太过繁琐,自由度不高,与组件的信息交互里十分不友好

  • Header这个问题在项目刚开始对我造成了很大的困扰,可能你有时都不知道在哪个navigation里配置header,有些页面不需要header这又是难以解决的坑,在stackoverflow和issue里也没找到合适的解决方案。
  • 在花费了长时间烦躁的探索后,我静下心来仔细想了一下,react-navigation的header是否有存在的必要?顿时我豁然开朗,header说到底其实也就是个标题栏,最多给你一个回退的Left按钮,但调用this.prop.navigation.goback(),同样也可以实现这一功能,所以为什么不自己封装一个header呢?
  • 如果header作为一个独立的组件,那么就可以在每一个页面里通过import作为组件的一部分,而不需要在navigation里进行参数式配置,这样就不需要受react-navigation的种种限制,与组件的交互也更加方便。
  • 对于Header的组件,我推荐react-native-navbar,结合项目需求进行组件封装

3、对于常见的‘底部标签式导航’布局,应该如何进行构建

  • [1] 首先,对于最外部的Navigator,需要考虑到加载页面,登录页面等,这些页面都是不需要回退的,只显示一次了,所以使用的是switchNavigator,具体代码如下:
const RootStack = createSwitchNavigator(
  {
    Splash: SplashScreen,
    App: AppStack,
    Login: LoginScreen
  },
  {
    initialRouteName: 'Splash'
  }
)

export default class App extends React.Component<Props> {
  render() {
    return (
      <RootStack
        ref={navigatorRef => {
          NavigationService.setTopLevelNavigator(navigatorRef)
        }}
      />
    )
  }
}
  • [2]其次是bottomTabNavigator,用于在每个Tab上呈现不同的页面,是APP的入口页面,代码如下:
const tabScreens = {
  first: {
    screen: FirstScreen,
    navigationOptions: {
      tabBarLabel: '首页',
      tabBarIcon: ({ tintColor }) => renderIcon('home', tintColor)
    }
  },
  message: {
    screen: MessageScreen,
    navigationOptions: {
      tabBarLabel: '消息',
      tabBarIcon: ({ tintColor }) => renderIcon('comments-o', tintColor)
    }
  },
  mine: {
    screen: MineScreen,
    navigationOptions: {
      tabBarLabel: '我的',
      tabBarIcon: ({ tintColor }) => renderIcon('user', tintColor)
    }
  }
}
const tabConfig = {
  tabBarPosition: 'bottom',
  tabBarOptions: {
    inactiveTintColor: '#a0a0a0',
    activeTintColor: basicColor.mainColor,
    indicatorStyle: { backgroundColor: 'transparent' },
    showIcon: true,
    style: {
      margin: 0,
      backgroundColor: '#ffffff',
      borderTopWidth: 0.66,
      borderTopColor: '#dddddd'
    },
    tabStyle: {
      padding: 0,
      margin: 0
    },
    labelStyle: {
      fontSize: 11,
      margin: 0,
      marginBottom: 5
    },
    iconStyle: {
      marginTop: -3,
      marginBottom: 0
    }
  },
  swipeEnabled: false
}
const HomeTab = createBottomTabNavigator(tabScreens, tabConfig)
  • [3]最后,是其他普通页面,一开始我是按照文档推荐的模式:在每一个Tab都建立一个StackNavigator,但是之后发现这样做太繁琐了,每个Tab多了一层stackNavigator不说,有些页面不属于任何Tab栈,那么其位置就很尴尬了,所以决定采用另一种模式:在switchNavigator的下一层创建一个StackNaviagtor,把TabNavigator也当成里面的一个screen,之后所有的需要回退的页面都作为screen存在这个stack里,screens文件夹下每一个文件夹都当是一个screen,用index.js作为出口。

4、在android上页面跳转如何实现ios左右切换的效果

其实react-navigation本身就实现了这个效果,目前文件在 'react-navigation/src/views/StackView/StackViewStyleInterpolator.js',可能版本更新之后又会改变路径

import StackStyleInterpolator from 'react-navigation/src/views/StackView/StackViewStyleInterpolator.js'
const AppStack = createStackNavigator(
  {
    Home: HomeScreen,
    Front: FrontScreen,
    Setting: SettingScreen
  },
  {
    headerMode: 'none',
    transitionConfig: () => ({
      //设置横向切换动画
      screenInterpolator: StackStyleInterpolator.forHorizontal
    })
  }
)

5、状态栏StatusBar的位置应该配置在哪

首先我们应该明白StatusBar对于不同的navigator有不同的表现形式:

1.在 SwitchNavigator中的页面配置:每一个页面的statusBar设置都不会影响到另外的页面

2.在StackNavigator、DrawerNavigator中的页面配置:每一次设置statusBar都会重新设置状态栏

3.在TabNavigator中的页面配置:只有页面第一次加载才会重新设置状态栏。

4.综上所诉,结合到项目具体的结构,我们只需要在项目的根Navigator添加

 <View style={{ flex: 1 }}>//注意,如果没有flex:1,则页面不会加载出来
        <StatusBar backgroundColor="transparent" translucent barStyle="dark-content" />
        <RootStack
          ref={navigatorRef => {
            NavigationService.setTopLevelNavigator(navigatorRef)
          }}
        />
      </View>

因为我们项目是采用半透明式状态栏,所以不需要考虑状态栏随不同页面改变而改变的情况,如果有需要可以参考基于路由的不同状态栏配置

6、如何跳转到一个不存在于当前navigator的页面(比如用户信息过期需跳转到登录界面)

  • 这个需要自己封装一个NavigationService,代码如下
import { NavigationActions, StackActions } from 'react-navigation'
let _navigator

function setTopLevelNavigator(navigatorRef) {
  _navigator = navigatorRef
}

function navigate(routeName, params) {
  _navigator.dispatch(
    NavigationActions.navigate({
      routeName,
      params
    })
  )
}

function resetTo(routeName) {
  const resetAction = StackActions.reset({
    index: 0,
    actions: [NavigationActions.navigate({ routeName: routeName })]
  })
  _navigator.dispatch(resetAction)
}
function goBack() {
  _navigator.dispatch(NavigationActions.back())
}
export default { navigate, resetTo, setTopLevelNavigator, goBack }

然后在根Navigator里调用setTopLevelNavigator

<RootStack
        ref={navigatorRef => {
          NavigationService.setTopLevelNavigator(navigatorRef)
        }}
      />

在其他地方调用NavigationService里的相应方法就可以从根导航器里跳转到任一个界面

7、如何在不传递navigation的情况下在自己封装的Header里调用goback()

  • 在NavigationService里创建goback()方法即可
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,816评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,729评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,300评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,780评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,890评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,084评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,151评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,912评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,355评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,666评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,809评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,504评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,150评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,121评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,628评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,724评论 2 351