Navigator算得上是react-native的核心组件之一,通过它基本上可以解决SPA里的历史管理功能,并且还自带跳转动画和后退手势,通过头部来控制页面跳转的APP基本上都要用到Navigator组件。Navigator的具体API官网都有,这里不做介绍。
本文主要说一些我使用中遇到的问题和其解决方案,包括如何管理整个router,如何自定义每个页面的头部左右按钮和一些自定义头部的样式,以及如何使Navigator可以和页面之间进行数据交互。
我们的APP整个是用Navigator来管理router,所以在入口文件中就直接配置Navigator,看index.ios.js
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | render() {return (
 <Navigator
 initialRoute={{name: 'home'}}
 renderScene={this.RouteMapper.bind(this)}
 configureScene={(route) => {
 if (route.sceneConfig) {
 return route.sceneConfig;
 }
 return Navigator.SceneConfigs.FloatFromRight;
 }}
 />
 );
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | const HomeView = require('./App/views/home');const LoginView = require('./App/views/login');
 
 RouteMapper(route, navigationOperations, onComponentRef) {
 let _navigator = navigationOperations;
 switch(route.name){
 case 'home':
 return (
 <HomeView userToken={route.userToken} navigator={_navigator} />
 );
 break;
 case 'login':
 return (
 <LoginView navigator={_navigator} />
 );
 break;
 }
 }
 
 | 
这里的代码很容易看懂,initialRoute属性传入初始化的页面name,所有的页面配置在RouteMapper中,并且定义一些页面之间需要传递的数据比如userToken或者是详情页的ID。主要的是在子页面中的render配置。我们可以看下HomeView:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 
 | constructor(props) {super(props);
 this.state = {
 message_count:0
 };
 let self = this;
 this.NavigationBarRouteMapper = {
 LeftButton(route, navigator, index, navState) {
 return (
 <TouchableOpacity
 onPress={() => navigator.parentNavigator.pop()}
 style={styles.leftIcon}>
 <Image
 style={styles.backIcon}
 source={require('../img/icon_back.png')}
 />
 </TouchableOpacity>
 );
 },
 RightButton(route, navigator, index, navState) {
 return (
 <TouchableOpacity
 onPress={() => navigator.parentNavigator.push({
 name: 'mymessage',
 userToken:self.thisToken
 })}
 style={styles.leftIcon}>
 <Image
 style={styles.messageIcon}
 source={require('../img/icon_messageheader.png')}
 />
 {self.setMessageTips()}
 </TouchableOpacity>
 );
 },
 Title(route, navigator, index, navState) {
 return null;
 }
 }
 }
 setMessageTips (){
 const {message_count} = this.state;
 if(message_count){
 return (
 <Text style={styles.messageTips}>{message_count}</Text>
 )
 }
 }
 render() {
 return (
 <Navigator
 renderScene={this.renderScene.bind(this)}
 navigator={this.props.navigator}
 navigationBar={
 <Navigator.NavigationBar style={styles.navBar}
 routeMapper={this.NavigationBarRouteMapper} />
 }
 />
 );
 }
 renderScene(route, navigator) {
 return (
 <View style={styles.container}>
 body
 </View>
 );
 }
 
 | 
所有页面的配置基本上类似,在子页面的render里再返回一个Navigator组件,它的renderScene来返回这个页面的实际body,它的navigationBar在子页面中重新定义,我是定义在constructor中,这样我们就可以完全控制每个页面的头部样式。并且可以进行子页面组件内的数据交互。