Navigator算得上是react-native的核心组件之一,通过它基本上可以解决SPA里的历史管理功能,并且还自带跳转动画和后退手势,通过头部来控制页面跳转的APP基本上都要用到Navigator组件。Navigator的具体API官网都有,这里不做介绍。
本文主要说一些我使用中遇到的问题和其解决方案,包括如何管理整个router,如何自定义每个页面的头部左右按钮和一些自定义头部的样式,以及如何使Navigator可以和页面之间进行数据交互。
我们的APP整个是用Navigator来管理router,所以在入口文件中就直接配置Navigator,看index.ios.js
1 2 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; }} /> ); }
|
1 2 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:
1 2 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中,这样我们就可以完全控制每个页面的头部样式。并且可以进行子页面组件内的数据交互。