新手理解Navigator的教程

注意!从RN 0.43版本开始,官方将停止维护Navigator,建议大家迁移到新的react-navigation库(文档地址需FQ)。新的导航库无论从性能还是易用性上都要大大好于老的Navigator!

下面是一个简单的例子,用Navigator来跳转页面,页面之间传递参数 (代码是ES6语法写的):

 import React from ‘react‘;
    import {
        View,
        Navigator
    } from ‘react-native‘;
    import FirstPageComponent from ‘./FirstPageComponent‘;

    export default class SampleComponent extends React.Component {
        render() {
            let defaultName = ‘FirstPageComponent‘;
            let defaultComponent = FirstPageComponent;
            return (
            <Navigator
              initialRoute={{ name: defaultName, component: defaultComponent }}
              configureScene={(route) => {
                return Navigator.SceneConfigs.VerticalDownSwipeJump;
              }}
              renderScene={(route, navigator) => {
                let Component = route.component;
                return <Component {...route.params} navigator={navigator} />
              }} />
            );
        }
    } 

这里来解释一下代码:

第三行: 一个初始首页的component名字,比如我写了一个component叫HomeComponent,那么这个name就是这个组件的名字【HomeComponent】了。

第四行: 这个组件的Class,用来一会儿实例化成 <Component />标签

第七行: initialRoute={{ name: defaultName, component: defaultComponent }} 这个指定了默认的页面,也就是启动app之后会看到界面的第一屏。 需要填写两个参数: name 跟 component。(注意这里填什么参数纯粹是自定义的,因为这个参数也是你自己发自己收,自己在renderScene方法中处理。我们这里示例用了两个参数,但其实真正使用的参数只有component)

第八,九,十行: configureScene={() => {
return Navigator.SceneConfigs.VerticalDownSwipeJump;
}} 这个是页面之间跳转时候的动画,具体有哪些?可以看这个目录下,有源代码的: node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js

最后的几行: renderScene={(route, navigator) => {
let Component = route.component;
return <Component {...route.params} navigator={navigator} />
}} />
);

这里是每个人最疑惑的,我们先看到回调里的两个参数:route, navigator。通过打印我们发现route里其实就是我们传递的name,component这两个货,navigator是一个Navigator的对象,为什么呢,因为它有push pop jump...等方法,这是我们等下用来跳转页面用的那个navigator对象。

return <Component {...route.params} navigator={navigator} />

这里有一个判断,也就是如果传递进来的component存在,那我们就是返回一个这个component,结合前面 initialRoute 的参数,我们就是知道,这是一个会被render出来给用户看到的component,然后navigator作为props传递给了这个component。

所以下一步,在这个FirstPageComponent里面,我们可以直接拿到这个 props.navigator:

import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import SecondPageComponent from ‘./SecondPageComponent‘;

export default class FirstPageComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }
    _pressButton() {
        const { navigator } = this.props;
        //为什么这里可以取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator作为props
        if(navigator) {
            navigator.push({
                name: ‘SecondPageComponent‘,
                component: SecondPageComponent,
            })
        }
    }
    render() {
        return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳转</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

这个里面创建了一个可以点击的区域,让我们点击可以跳到SecondPageComponent这个页面,实现页面的跳转。
现在来创建SecondPageComponent,并且让它可以再跳回FirstPageComponent:

import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import FirstPageComponent from ‘./FirstPageComponent‘;

export default class SecondPageComponent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {};
    }

    _pressButton() {
        const { navigator } = this.props;
        if(navigator) {
            //很熟悉吧,入栈出栈~ 把当前的页面pop掉,这里就返回到了上一个页面:FirstPageComponent了
            navigator.pop();
        }
    }

    render() {
    return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳回去</Text>
                </TouchableOpacity>
            </View>
    );
    }
}

大功告成,能进能出了。

关于官方文档里有个东西,这里说一下:

getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些
jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。
jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了
jumpTo(route) - Transition to an existing scene without unmounting
push(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward to
pop() - Transition back and unmount the current scene
replace(route) - Replace the current scene with a new route
replaceAtIndex(route, index) - Replace a scene as specified by an index
replacePrevious(route) - Replace the previous scene
immediatelyResetRouteStack(routeStack) - Reset every scene with an array of routes
popToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmounted
popToTop() - Pop to the first scene in the stack, unmounting every other scene

这些都是navigator可以用的public method,就是跳转用的,里面有些带参数的XXX(route),新手第一次看这个文档会疑惑,这个route参数是啥呢,这个route就是:

renderScene={(route, navigator) =>

这里的route,最基本的route就是:

var route = {
    component: LoginComponent
}

这种格式。这个地方有点模糊的,在这里先说清楚了。

然后下面要讨论,怎么传递参数过去,或者从对方获取参数。
传递参数,通过push就可以了。
比如在一个 press的事件里:

//FirstPageComponent.js
import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import SecondPageComponent from ‘./SecondPageComponent‘;

export default class FirstPageComponent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            id: 2
        };
    }

    _pressButton() {
        const { navigator } = this.props;
        if(navigator) {
            navigator.push({
                name: ‘SecondPageComponent‘,
                component: SecondPageComponent,
                //这里多出了一个 params 其实来自于<Navigator 里的一个方法的参数...
                params: {
                    id: this.state.id
                }
            });
        }
    }

    render() {
        return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳转并传递id</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

params的来历:

// index.ios.js
<Navigator
  initialRoute={{ name: defaultName, component: defaultComponent }}
  configureScene={() => {
    return Navigator.SceneConfigs.VerticalDownSwipeJump;
  }}
  renderScene={(route, navigator) => {
    let Component = route.component;
    if(route.component) {
        //这里有个 { ...route.params }
        return <Component {...route.params} navigator={navigator} />
    }
  }} />

这个语法是把 routes.params 里的每个key 作为props的一个属性:

navigator.push({
    name: ‘SecondPageComponent‘,
    component: SecondPageComponent,
    params: {
        id: this.state.id
    }
});

这里的 params.id 就变成了 <Navigator id={} 传递给了下一个页面。
所以 SecondPageComponent就应该这样取得 id:

//SecondPageComponent.js
import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import FirstPageComponent from ‘./FirstPageComponent‘;

export default class SecondPageComponent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            id: null
        }
    }

    componentDidMount() {
        //这里获取从FirstPageComponent传递过来的参数: id
        this.setState({
            id: this.props.id
        });
    }

    _pressButton() {
        const { navigator } = this.props;
        if(navigator) {
            navigator.pop();
        }
    }

    render() {
        return (
            <View>
                <Text>获得的参数: id={ this.state.id }</Text>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳回去</Text>
                </TouchableOpacity>
            </View>
        );
    }
}

这样在页面间传递的参数,就可以获取了。

@sunnylqm 很多人不理解这里的params,我忍不住稍微补充一下。

然后就是返回的时候,也需要传递参数回上一个页面:
但是navigator.pop()并没有提供参数,因为pop()只是从 [路由1,路由2,路由3。。。]里把最后一个路由踢出去的操作,并不支持传递参数给倒数第二个路由,这里要用到一个概念,把上一个页面的实例或者回调方法,作为参数传递到当前页面来,在当前页面操作上一个页面的state:

这是一个查询用户信息的例子,FirstPageComponent传递id到SecondPageComponent,然后SecondPageComponent返回user信息给FirstPageComponent

//FirstPageComponent.js
import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import SecondPageComponent from ‘./SecondPageComponent‘;

export default class FirstPageComponent extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            id: 2,
        user: null,
        }
    }

    _pressButton() {
        let _this = this;
        const { navigator } = this.props;
        if(navigator) {
            navigator.push({
                name: ‘SecondPageComponent‘,
                component: SecondPageComponent,
                params: {
                    id: this.state.id,
                    //从SecondPageComponent获取user
                    getUser: function(user) {
                        _this.setState({
                            user: user
                        })
                    }
                }
            });
        }
    }

    render() {
        if( this.state.user ) {
            return(
                <View>
                    <Text>用户信息: { JSON.stringify(this.state.user) }</Text>
                </View>
            );
        }else {
            return(
                <View>
                    <TouchableOpacity onPress={this._pressButton.bind(this)}>
                        <Text>查询ID为{ this.state.id }的用户信息</Text>
                    </TouchableOpacity>
                </View>
            );
        }

    }
}

然后再操作SecondPageComponent:

//SecondPageComponent.js

const USER_MODELS = {
    1: { name: ‘mot‘, age: 23 },
    2: { name: ‘晴明大大‘, age: 25 }
};

import React from ‘react‘;
import {
    View,
    Navigator
} from ‘react-native‘;

import FirstPageComponent from ‘./FirstPageComponent‘;

export default class SecondPageComponent extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            id: null
        }
    }

    componentDidMount() {
        //这里获取从FirstPageComponent传递过来的参数: id
        this.setState({
            id: this.props.id
        });
    }

    _pressButton() {
            const { navigator } = this.props;

            if(this.props.getUser) {
                let user = USER_MODELS[this.props.id];
                this.props.getUser(user);
            }

            if(navigator) {
                navigator.pop();
            }
    }

    render() {
        return(
            <View>
                <Text>获得的参数: id={ this.state.id }</Text>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳回去</Text>
                </TouchableOpacity>
            </View>
        );
    }
}
看下效果如何吧。

放个类似的例子代码: https://github.com/mozillo/navigation
安装方法: npm install && react-native run-android
时间: 2024-12-12 19:49:06

新手理解Navigator的教程的相关文章

浅析安卓和苹果的架构区别,为何苹果顺畅安卓卡?适合新手理解

iOS对屏幕反应的优先级是最高的,它的响应顺序依次为Touch--Media--Service--Core架构,当用户触摸接触了屏幕时,系统最先去处理屏幕显示也就是Touch这个层级,然后才是媒体.服务以及Core架构等.而Android系统的优先级响应层级则是Application--Framework--Library--Kernal架构,和显示相关的图形处理属于Library,被“放到”了第三位.一句话概念就是,当你触摸屏幕之后Android系统首先会激活应用框架,然后是屏幕,最后是核心架

Cocos2d-x 3.2 android平台新手开发环境配置教程

参考: http://www.cocoachina.com/cocos/20140529/8596.html 以下内容参考了 cocoachina 中的开发环境配置教程 http://www.cocoachina.com/cocos/20140529/8596.html ,我觉得里面的配置过程,不是很详细,自己在这篇博文的基础上完善了哈,有什么问题,可以留言交流. 前一段时间,学习android开发后,想想做做好玩的游戏玩玩,现在就学习cocos2d-x 3.2,想了解哈,这个游戏引擎-- 学习

【原创】新手理解HTML、CSS、javascript直接的关系

工作多年,一直忙忙碌碌的应用各种技术,现在不忙了,问问自己究竟在做什么,究竟会什么竟答不上来,回想起来工作中经常是被要求多快好省的去实现一个目标,用度娘解决问题,却没时间了解原因,今天就从宏观的角度入手来归纳总结一下. 一.HTML.CSS.JavaScript简介及简单分工 1.什么是HTML(超文本标记语言 Hyper Text Markup Language),HTML 是用来描述网页的一种语言.2.CSS(层叠样式表 Cascading Style Sheets),样式定义如何显示 HT

文件内容转换多层字典(适合新手理解)

#!/usr/bin/env python#-*- coding:UTF-8 -*-flag = 0return_flag = 0f = open("file3.txt","r",encoding = "utf-8")dict1 = {}dict2 = {}dict3 = {}dict4 = {}dict5 = {}dict6 = {}ZN = {}MSK = {}US = {}info1 = {}for i in f: if "中国&

新手理解的bash环境变量解析漏洞

p{ line-height:150%; font-size:18px; font-family:fangsong; margin-top:20px; } pre {font-size:15px; background-color:black; color: white;font-family: sans-serif } #refer{background-color:gray;} h1 {font-family:simhei;} 1 环境变量是什么 无论是Windows程序还是Linux程序,

DOS批处理高级教程

转载-->http://blog.csdn.net/lanbing510/article/details/7461073 前言 本教程主要引用伤脑筋版主的系列文章,同时参考引用[英雄]教程等其他批处理教程,本文将这些文章合并在一起,并尽量修改得详细而且简单易懂,修改整理也是学习过程,主要目的是方便自己以后查阅.    本教程很长啊,需要一定的耐心才能看完,能够看完的话,差不多就是批处理高手了,即使不是高手也是熟手了.本教程还在不断补充之中,当有比较典型的应用技巧时,本教材会将其收入相关的章节之中

移动开发:给安卓软件开发初学者简单的教程

如果你想学习安卓软件开发,还是个初学者,可以在网上找到很多的安卓教程和学习材料,眼花缭乱的初学者教程和进阶教程,如果您看到这篇文章就不要错过,简直是初学者的福音. 考虑到有如此多的信息你又是初学者,所以你很容易感到迷惑不知道从哪开始.为了让你感到轻松同时消除有很多很好的教程要学习的假象,可以从下面这12篇教程开始着手. 初学者不用关注所有的教程,也不用关注某一教程里的全部内容.因为其中的一些教程是为初学者设计,但渐渐会深入一些高级话题.所以,如果你无法理解每篇教程的全部内容,别灰心. 如果哪里遇

Swift开发教程

IOS开发视频教程非常全面,总共39G,系统的介绍了Swift这门苹果今年推出的开发语言.苏苏是也是一个IOS开发小菜,Swift比Objective-C更加容易让新手理解,如果希望能进入IOS这个高帅富程序员行列,下载它学习吧. 教程目录: 第1季 Swift基础语法 第2季 Swift高级语法 第3季 构建Swift UI 第4季 Swift微信 From:http://www.2cifang.com/thread-612-1-1.html 另外还可以参看: 苹果Swift编程语言入门教程[

成为Emacs高手01-学习自带教程

Emacs 快速指南. [注意:位于[]之间的内容是译注,比如本行,下同.] Emacs 键盘命令通常包含 CONTROL 键(有时候以 CTRL 或 CTL 来标示)和META 键(有时候用 EDIT 或 ALT 来标示).为了避免每次都要写出全名,我们约定使用下述缩写: C-<chr>  表示当输入字符 <chr> 时按住 CONTROL 键. 因此 C-f 就表示:按住 CONTROL 键再输入 f. M-<chr>  表示当输入字符 <chr> 时按