ReactNative的Navigator组件使用方式

作者: SpikeKing | 来源:发表于2016-04-19 11:38 被阅读27060次

    欢迎Follow我的GitHub, 关注我的简书.

    React Native的编程思想类似于iOS, 导航栏也使用Navigator作为标识, 类似于AndroidActionBar. 导航栏作为最重要的应用组件之一, 除了处理页面导航功能以外, 还会提供页面栈的管理, 管理页面的跳入和跳出. 本文介绍 Navigator 组件的使用方式.

    React Native

    本文源码的GitHub下载地址

    关于React Native项目的启动, 参考1, 参考2.


    简单使用

    Navigator

    添加 Navigator 的组件<Navigator/>. 设置方法: 初始化路由(initialRoute), 配置场景动画(configureScene), 渲染场景(renderScene). 初始化路由(initialRoute), 使用FirstPage页面作为首页.

    // 主模块
    class SimpleView extends Component {
      // ...
      render() {
        return (
          <Navigator
            style={{flex:1}}
            initialRoute={{component: FirstPage}}
            configureScene={this.configureScene}
            renderScene={this.renderScene}/>
        );
      }
    }
    

    配置场景动画(configureScene): 根据路由的type属性, 判断使用的动画样式, 底部弹出或右侧弹出.

      /**
       * 配置场景动画
       * @param route 路由
       * @param routeStack 路由栈
       * @returns {*} 动画
       */
      configureScene(route, routeStack) {
        if (route.type == 'Bottom') {
          return Navigator.SceneConfigs.FloatFromBottom; // 底部弹出
        }
        return Navigator.SceneConfigs.PushFromRight; // 右侧弹出
      }
    

    渲染场景(renderScene): 使用动态加载组件的方式. 设置加载页面的navigator参数, 其余使用route.passProps属性传递其他参数.

      /**
       * 使用动态页面加载
       * @param route 路由
       * @param navigator 导航器
       * @returns {XML} 页面
       */
      renderScene(route, navigator) {
        return <route.component navigator={navigator}  {...route.passProps} />;
      }
    

    也可以使用静态加载组件, 需要预定义组件, 没有动态加载灵活.

      /**
       * 渲染场景, 通过不同参数, 设置不同页面
       * @param route 路由, 场景信息
       * @param navigator 导航器
       * @returns {XML} 页面
       */
      renderScene(route, navigator) {
        if (route.name == 'FirstPage') {
          return <FirstPage navigator={navigator} {...route.passProps}/>
        } else if (route.name == 'SecondPage') {
          return <SecondPage navigator={navigator} {...route.passProps}/>
        }
      }
    

    第一页

    FirstPage组件: 包含导航栏标题和两个跳转按钮. 提供两种跳转动画, 右出和底部. 点击按钮调用_navigate()方法, 跳转到第二页.

    // 第一页. 使用Component可以自动生成注释, 符合标准
    class FirstPage extends Component {
    
      // ...
      
      render() {
        return (
          <View style={styles.container}>
            <View style={styles.heading}>
              <Text style={styles.headText}>
                {'第一页'}
              </Text>
            </View>
            <TouchableOpacity
              style={styles.button}
              onPress={()=>this._navigate('你好! (来源第一页:右出)')}>
              <Text style={styles.buttonText}>
                {'跳转至第二页(右出)'}
              </Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={styles.button}
              onPress={()=>this._navigate('你好! (来源第一页:底出)', 'Bottom')}>
              <Text style={styles.buttonText}>
                {'跳转至第二页(底部)'}
              </Text>
            </TouchableOpacity>
          </View>
        );
      }
    }
    

    也可以使用var FirstPage = React.createClass()创建组件, 但没有使用继承Component方式规范, 不能自动生成注释.

    第一页

    _navigate()方法: 导航跳转, 调用navigator.push()方法. 传递参数passPropsname属性, type动画类型, component跳转组件.

      /**
       * 给Navigator传递参数.
       * @param name 参数
       * @private
       */
      _navigate(name, type = 'Normal') {
        this.props.navigator.push({
          component: SecondPage,
          passProps: {
            name: name
          },
          type: type
        })
      }
    

    下划线表示私有方法, 类似Java的private限定符.

    第二页

    SecondPage组件: 第二页, 跳出返回第一页. 调用navigator.pop()方法, 使用当前页面出栈, 显示上一个栈内页面.

    // 第二页, 点击跳出返回第一页
    class SecondPage extends Component {
      render() {
        return (
          <View style={styles.container}>
            <View style={styles.heading}>
              <Text style={styles.headText}>
                第二页: {this.props.name}
              </Text>
            </View>
            <TouchableOpacity
              style={styles.button}
              onPress={()=>this.props.navigator.pop()}>
              <Text style={styles.buttonText}>
                返回上一页
              </Text>
            </TouchableOpacity>
          </View>
        );
      }
    }
    
    第二页

    Navigator的主要功能, 是管理页面栈, 控制页面的跳入跳出.


    统一导航栏

    对于应用而言, 需要统一的导航栏, Navigator 组件也提供导航栏的定制.

    Navigator

    与上文类似, 额外添加navigationBar的属性, 自定义设置导航栏, 保持所有页面的导航栏一致. 属性添加<NavigationBar/>标签, 通过routeMapper控制导航栏的功能和样式.

    // 主模块
    class UniformView extends Component {
      //...
    
      render() {
        return (
          <Navigator
            style={{flex:1}}
            initialRoute={{name: 'FirstPage', component: FirstPage}}
            configureScene={this.configureScene}
            renderScene={this.renderScene}
            navigationBar={
              <Navigator.NavigationBar
                style={styles.navContainer}
                routeMapper={NavigationBarRouteMapper}/>}
            />
        );
      }
    }
    

    NavigationBarRouteMapper

    NavigationBarRouteMapper: 导航栏路由映射器, 设置左键LeftButton, 右键RightButton, 标题Title.

    // 导航栏的Mapper
    var NavigationBarRouteMapper = {
      // 左键
      LeftButton(route, navigator, index, navState) {
        // ...
      },
      // 右键
      RightButton(route, navigator, index, navState) {
        // ...
      },
      // 标题
      Title(route, navigator, index, navState) {
        return (
          <View style={styles.navContainer}>
            <Text style={styles.title}>
              应用标题
            </Text>
          </View>
        );
      }
    };
    

    左键LeftButton: index属性表示当前页面的索引, 通过判断index属性, 获知栈内是否有其他页面, 判断后退按钮是否显示. 点击调用navigator.pop()出栈.

      // 左键
      LeftButton(route, navigator, index, navState) {
        if (index > 0) {
          return (
            <View style={styles.navContainer}>
              <TouchableOpacity
                underlayColor='transparent'
                onPress={() => {if (index > 0) {navigator.pop()}}}>
                <Text style={styles.leftNavButtonText}>
                  后退
                </Text>
              </TouchableOpacity>
            </View>
          );
        } else {
          return null;
        }
      },
    

    右键RightButton: 点击调用路由(route)onPress()方法, 提示信息. 根据路由的rightText属性添加显示文字.

      // 右键
      RightButton(route, navigator, index, navState) {
        if (route.onPress)
          return (
            <View style={styles.navContainer}>
              <TouchableOpacity
                onPress={() => route.onPress()}>
                <Text style={styles.rightNavButtonText}>
                  {route.rightText || '右键'}
                </Text>
              </TouchableOpacity>
            </View>
          );
      },
    
    导航栏

    第一页/第二页

    第一页与第二页与上文类似, 当第一页跳转时, 传递的路由信息有些变化, 控制第二页与导航栏的显示信息.

      // 填出提示框
      onPress() {
        alert("我是Spike!");
      }
    
      /**
       * 跳转页面至SecondPage
       * @param name 传递参数
       * @param type 动画类型
       */
      gotoNext(name, type = 'Normal') {
        this.props.navigator.push({
          component: SecondPage,
          passProps: {
            id: name
          },
          onPress: this.onPress,
          rightText: 'ALERT!',
          type: type
        })
      }
    

    React Native 路由的基本功能就是这些, 控制页面的切换, 控制导航栏的功能. 导航栏作为应用最重要的组件之一, 一定要熟练掌握.

    OK, that's all ! Enjoy it!

    相关文章

      网友评论

      • 9岁就很6:报错了,不能直接运行,一对红色的
      • cd669ffe9f5f:查了下网上的其他教程,这篇写的最通俗易懂,感谢作者
      • 77089d60ea4c: Navigator 是导入过后就可以直接使用吗 不需要安装什么的吗?
      • 默默的前行:我用react-native-tab-navigator和navigator组合,但是一级页面导航栏上的标题该怎么显示那,求解答
      • 7eb2a919479b:感谢分享, 很实用!
      • 白云之巅1992:楼主你好,有个问题想请教下。

        我现在的需求是需要两种Navigationbar,一种高度为44默认的就能实现,一种高度为50并且中间的title部分是两个标题(一上一下),这种情况有没有好的解决方法?并且第二种下面的标题文字要求会改变,我制作的时候应该考虑什么?
        白云之巅1992:我看demo里都是在iOS.js里实现navigation,我这两种的应该怎么实现呢?
      • 夏午茶丶先生:_navigate(name, type = 'Normal') 里面的 第二个参数 type = 'Normal'是什么 传的是什么
      • 木易宗龙:上个链接
        SpikeKing:@木易宗龙 仔细读.
      • 木易宗龙:demo在哪,不上demo的话对新手来说,不好学习
      • biglyn:已解决,用了三方库react native simple router 满足需求.
      • biglyn:请问大神~我的navigationbar想在外部修改,应该如何去做,就是在每个界面显示不同的navigationbar里的rightbutton,但我不想全部都写在NavigationBarRouteMapper中,这样自定义的navigation文件中代码太长,且分支太多,我想抽取出来,在每个界面上修改它,并且能够在界面上响应navbarRightbar事件,应该怎么做…不知道有没有表达清楚,这个问题困扰我挺长时间了。
      • Bill_Chow:我想问一下啊关于navigationbar 在android中不能居中,这是什么问题??
      • victoria_purple:有没有源码链接啊?
        Bill_Chow:@victoria_purple 有地址啊
      • dongwenbo:我太笨了,连这个项目怎么运行都不知道 :joy:
        SpikeKing: @dongwenbo RN其实蛮有意思的
        dongwenbo:@SpikeKing 运行出来了,谢谢,npm install
        SpikeKing:@dongwenbo 哈哈, 看这一行: 关于React Native项目的启动, 参考1, 参考2.
      • zhuhf:今天正好看到这块,尤其是定制导航栏,看的云里雾里,官方说明也没查到。
        SpikeKing:@hiphonezhu 有Demo,结合代码看比较好
      • littl_Prince:你这是用ES6写的吗
        SpikeKing:@颜卿今天Coding了吗 RN是复用逻辑,一套代码轻松移植Android和iOS,目前还在完善中。多写多练,多看Demo。
        littl_Prince:@SpikeKing 我把官方React教程学完以后不知道怎么办呢 做项目吧 我觉得组件化优势我没看出来,能指点一下吗?
        SpikeKing:@颜卿今天Coding了吗 恩! JS的代码
      • 峂峂:很好
        SpikeKing:@峂峂 希望有所收获~

      本文标题:ReactNative的Navigator组件使用方式

      本文链接:https://www.haomeiwen.com/subject/sbaalttx.html