React Native导航控制器用法简介

React Native封装了许多控件,并且提供了比较详细的文档和代码片段,但并不是所有的示例都能够清楚的说明这些控件的用法,其中就包括重要的Navigator(导航控制器)。官方的文档中贴了许多代码,但并没有说清楚它是怎么工作的。

在iOS中,我们使用UINavigationController管理多个页面,每个被它所管理的页面都有一个引用指向所在的导航控制器对象。我们可以很方便的利用这个特性管理页面(pushpop)。不过React Native中的Navigator的使用方式不一样,它使用一个集中的路由机制控制页面的跳转,下面我们会通过一个简单的例子详细进行讲解。

1. 创建React Native项目

React Native可以用于现有的项目,为了简单起见,我们使用一个全新的项目开始。

$ react-native init NavigatorDemo
This will walk you through creating a new React Native project in ~/NavigatorDemo
Installing react-native package from npm...
Setting up new React Native app in ~/NavigatorDemo
NavigatorDemo@0.0.1 ~/NavigatorDemo
└── react@15.2.1 

To run your app on iOS:
   cd ~/NavigatorDemo
   react-native run-ios
   - or -
   Open ~/NavigatorDemo/ios/NavigatorDemo.xcodeproj in Xcode
   Hit the Run button
To run your app on Android:
   Have an Android emulator running (quickest way to get started), or a device connected
   cd ~/NavigatorDemo
   react-native run-android

react-native会自动创建一下项目内容:

$ ls
android index.android.js index.ios.js ios node_modules package.json

其中index.android.jsindex.ios.js分别为Android和iOS应用的入口。为了能够更好地看清楚页面结构,我们新建一个js目录用于存放页面代码。

$ mkdir js
$ cd js
$ touch FirstScene.js
$ touch SecondScene.js
$ ls
FirstScene.js SecondScene.js

FirstScene.jsSecondScene.js为两个页面控件。

2. 准备工作

下面以index.ios.js为例进行讲解。默认该文件中有许多自动生成的代码,将其修改为以下样子。

//1. 导入react框架中的内容
import React, { Component } from 'react';
//2. 导入react-native框架中的内容
import {
  //3. 必须,注册应用(App)时使用
  AppRegistry, 
} from 'react-native';

//4. 创建应用
class NavigatorDemo extends Component {
  render() {
    return (
      //5. 编写应用的渲染代码
    );
  }
}

//5. 注册应用组件
AppRegistry.registerComponent('NavigatorDemo', () => NavigatorDemo);

可以看出React Native应用的结构还是很简单的。接下来就开始编写导航控制器相关内容。在使用之前需要导入一下组件:NavigatorViewTextTouchableHighlight等。

import {
  AppRegistry,
  Text,
  View,
  Navigator,
  TouchableHighlight,
} from 'react-native';

导入刚才创建的页面组件:

import FirstScene from './js/FirstScene.js';
import SecondScene from './js/SecondScene.js';

接下来就可以使用这两个JS文件中的内容。

3. Navigator的使用

作为页面管理者,Navigator也是一个继承字Component的组件,需要最先渲染。

class NavigatorDemo extends Component {
  render() {
    return (
      //1. 使用导航控制器
      <Navigator
        //2. 设置初始页面
        initialRoute={{name: 'First'}}
        //3. 设置路由表
        renderScene={(route, navigator) => {
          //4. 更加名称路由
          switch (route.name) {
            case 'First':
              return (
                //4.1 渲染页面,并且传入导航控制器,方便页面内使用
                <FirstScene title={route.name} navigator={navigator}/>
              );
            case 'Second':
              return (
                <SecondScene title={route.name} navigator={navigator}/>
              );
          }
        }}
    />
   );
}

导航控制器有两个非常重要的属性initialRouterenderScene,整个页面的管理就依靠这两个属性的设置。其中initialRoute用于设置初始页面(第一个页面);而renderScene设置页面路由信息。

其中initialRoute的值就是页面路由时的第一个参数route对象,因此可以在里面设置任意需要在路由时使用的信息,其中最重要的是需要有一个能够区分页面的标识,这里我们使用name进行区分。

//2. 设置初始页面
initialRoute={{name: 'FirstScene'}}

renderScene是一个路由函数,导航控制器中的每个页面显示前都会调用该函数,从而根据传递的参数(route)获取对应的页面。

//3. 设置路由表
renderScene={(route, navigator) => {
  //4. 更加名称路由
  switch (route.name) {
    case 'First':
      return (
        //4.1 渲染页面,并且传入导航控制器(navigator),方便页面内使用
        <FirstScene title={route.name} navigator={navigator}/>
      );
    case 'Second':
      return (
        <SecondScene title={route.name} navigator={navigator}/>
      );
  }
}}

4. 页面跳转

官方以及网络上的许多示例都是将所有代码写在index.ios.js中,在实际应用中几乎不存在这种情况。因此我们将页面组件分别写在两个不同的文件FirstScene.jsSecondScene.js中。其中第一个页面内容为:

import React, { Component } from 'react';
import {
  View,
  Text,
  TouchableHighlight,
} from 'react-native';

//1. 导出默认类,一定不能忘记export default导出
export default class FirstScene extends Component {

  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <TouchableHighlight onPress={() => {
          //2. 使用props获取传入的navigator并使用route对象作为参数,跳转到新的页面
          this.props.navigator.push({name: 'Second'});
        }}>
          <Text>{this.props.title}</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

第二个页面的内容为:

import React, { Component } from 'react';
import {
  View,
  Text,
  TouchableHighlight,
} from 'react-native';

//1. 导出默认类
export default class SecondScene extends Component {
  render() {
    return (
      <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
        <TouchableHighlight onPress={() => {
          //2. 使用传入的导航控制器进行跳转,返回上一页
          this.props.navigator.pop();
        }}>
          <Text>{this.props.title}</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

很容易可以看出,其实每个页面也只是一个简单的组件,并不是什么特殊的东西。只不过很多人都被卡在了导航控制器(navigator)的获取上,因为React Native并不会像iOS一样自动将navigator传入页面。

注意:页面跳转时,不管是push还是pop都会先调用navigatorrenderScene方法。

5. 参考资料

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

推荐阅读更多精彩内容