Hello Mobile Navigation - 你好,手机导航!

让我们使用React Navigation为Android和iOS构建一个简单的聊天类应用程序。

设置和安装

首先,在开始之前,确保你已经设置好了React Native,接下来,创建一个新的项目,并添加react-navigation:

  1. # Create a new React Native App
  2. react-native init SimpleApp
  3. cd SimpleApp
  4. # Install the latest version of react-navigation from npm
  5. npm install --save react-navigation
  6. # Run the new app
  7. react-native run-android
  8. # or:
  9. react-native run-ios

如果你使用的是create-react-native-app,而不是react-native init:

  1. # Create a new React Native App
  2. create-react-native-app SimpleApp
  3. cd SimpleApp
  4. # Install the latest version of react-navigation from npm
  5. npm install --save react-navigation
  6. # Run the new app
  7. npm start
  8. # This will start a development server for you and print a QR code in your terminal.

确认你能成功看到在iOS/Android上运行的示例应用程序:

Hello Mobile Navigation - 你好,手机导航! - 图1 Hello Mobile Navigation - 你好,手机导航! - 图2



我们希望在iOS和Android上代码共享,所以删除index.js里的内容(如果你使用的是0.49之前的React Native,你需要删除index.ios.jsindex.android.js里的内容),取而代之的是import './App';。此后,为了实现应用,需要创建新的文件App.js(如果你使用的是create-react-native-app命令创建的应用,这一步已经自动完成了)。

介绍Stack Navigator

我们打算在我们的app里使用StackNavigator,因为从概念上来说,我们想要获得一种“卡片式堆栈”的移动效果,也就是说把每个新的页面放到栈顶,返回时从栈顶移除。我们先从一个页面开始:

  1. import React from 'react';
  2. import {
  3. AppRegistry,
  4. Text,
  5. } from 'react-native';
  6. import { StackNavigator } from 'react-navigation';
  7. class HomeScreen extends React.Component {
  8. static navigationOptions = {
  9. title: 'Welcome',
  10. };
  11. render() {
  12. return <Text>Hello, Navigation!</Text>;
  13. }
  14. }
  15. export const SimpleApp = StackNavigator({
  16. Home: { screen: HomeScreen },
  17. });
  18. AppRegistry.registerComponent('SimpleApp', () => SimpleApp);

如果你是使用create-react-native-app命令创建的app,则自带的App.js文件将要被修改为:

  1. import React from 'react';
  2. import { StyleSheet, Text, View } from 'react-native';
  3. import { StackNavigator } from 'react-navigation';
  4. class HomeScreen extends React.Component {
  5. static navigationOptions = {
  6. title: 'Welcome'
  7. };
  8. render() {
  9. return <Text>Hello, Navigation!</Text>;
  10. }
  11. }
  12. const SimpleApp = StackNavigator({
  13. Home: { screen: HomeScreen }
  14. });
  15. export default class App extends React.Component {
  16. render() {
  17. return <SimpleApp />;
  18. }
  19. }
  20. const styles = StyleSheet.create({
  21. container: {
  22. flex: 1,
  23. backgroundColor: '#fff',
  24. alignItems: 'center',
  25. justifyContent: 'center'
  26. }
  27. });

界面的title是可以在静态对象navigationOptions中配置的,其中可以设置多个选项来配置导航器中页面的呈现方式。

现在iPhone和Android应用程序应该会显示相同的页面:

Hello Mobile Navigation - 你好,手机导航! - 图3 Hello Mobile Navigation - 你好,手机导航! - 图4


添加一个新的页面

接下来,在我们的App.js文件中,添加一个新页面,叫做:ChatScreen,把它定义在HomeScreen的下面:

  1. // ...
  2. class HomeScreen extends React.Component {
  3. //...
  4. }
  5. class ChatScreen extends React.Component {
  6. static navigationOptions = {
  7. title: 'Chat with Lucy',
  8. };
  9. render() {
  10. return (
  11. <View>
  12. <Text>Chat with Lucy</Text>
  13. </View>
  14. );
  15. }
  16. }

然后,我们在HomeScreen组件中添加一个按钮,从而可以跳转到ChatScreen:跳转需要使用navigate提供的方法(navigate是界面的navigation的一个属性),通过给方法传入一个目标routeName进行跳转,在这里,我们的目标界面是Chat

  1. class HomeScreen extends React.Component {
  2. static navigationOptions = {
  3. title: 'Welcome',
  4. };
  5. render() {
  6. const { navigate } = this.props.navigation;
  7. return (
  8. <View>
  9. <Text>Hello, Chat App!</Text>
  10. <Button
  11. onPress={() => navigate('Chat')}
  12. title="Chat with Lucy"
  13. />
  14. </View>
  15. );
  16. }
  17. }

(不要忘记从react-native导入View和Button: import { AppRegistry, Text, View, Button } from 'react-native';

到此,任务还没有完成,我们还需要在StackNavigator中注册Chat,像下面这样:

  1. export const SimpleApp = StackNavigator({
  2. Home: { screen: HomeScreen },
  3. Chat: { screen: ChatScreen },
  4. });

现在你可以导航到你的新页面,并且能够返回:


Hello Mobile Navigation - 你好,手机导航! - 图5 Hello Mobile Navigation - 你好,手机导航! - 图6


传递参数

硬编码写死ChatScreen的标题方式有点不太好,如果我们能够传递一个名字来渲染,将会更有用,让我们来这样做。

除了在导航函数中指定目标routeName外,还可以向新路由传递参数。首先,我们来编辑HomeScreen组件,传递一个user给路由。

  1. class HomeScreen extends React.Component {
  2. static navigationOptions = {
  3. title: 'Welcome',
  4. };
  5. render() {
  6. const { navigate } = this.props.navigation;
  7. return (
  8. <View>
  9. <Text>Hello, Chat App!</Text>
  10. <Button
  11. onPress={() => navigate('Chat', { user: 'Lucy' })}
  12. title="Chat with Lucy"
  13. />
  14. </View>
  15. );
  16. }
  17. }

然后我们可以编辑我们的ChatScreen组件,来显示通过路由传入的user参数:

  1. class ChatScreen extends React.Component {
  2. // Nav options can be defined as a function of the screen's props:
  3. static navigationOptions = ({ navigation }) => ({
  4. title: `Chat with ${navigation.state.params.user}`,
  5. });
  6. render() {
  7. // The screen's current route is passed in to `props.navigation.state`:
  8. const { params } = this.props.navigation.state;
  9. return (
  10. <View>
  11. <Text>Chat with {params.user}</Text>
  12. </View>
  13. );
  14. }
  15. }

现在,当你导航到Chat页面时,你就可以看到上述的标题。尝试改变HomeScreen里的user参数,看看会发生什么!


Hello Mobile Navigation - 你好,手机导航! - 图7 Hello Mobile Navigation - 你好,手机导航! - 图8