新手理解Navigator的教程

Navigator是RN提供的一个路由工具,不过缺陷是没有预设一个路由配置文件,因此致使整个结构相似goto语法的,你能够跳转到任意的页面。先来一个最简单的Navigator:node

var {
    View,
    Navigator
} = React;var FirstPageComponent = require('./FirstPageComponent');var SampleComponent = React.createClass({
    render: function() {        var defaultName = 'FirstPageComponent';        var defaultComponent = FirstPageComponent;        return (
        <Navigator
          initialRoute={{ name: defaultName, component: defaultComponent }}
          configureScene={() => {            return Navigator.SceneConfigs.VerticalDownSwipeJump;
          }}
          renderScene={(route, navigator) => {            let Component = route.component;            if(route.component) {              return <Component {...route.params} navigator={navigator} />
            }
          }} />
        );

    }
});

这里来逐行解释代码的功效:react

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

第四行: 这个组件的Class,用来一下子实例化成 <Component />标签react-native

第七行: initialRoute={{ name: defaultName, component: defaultComponent }} 这个指定了默认的页面,也就是启动app以后会看到界面的第一屏。 须要填写两个参数: name 跟 component。app

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

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

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

if(route.component) { 
    return <Component {...route.params} navigator={navigator} />
}

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

因此下一步,在这个FirstPageComponent里面,咱们能够直接拿到这个 props.navigator:code

var {
    View,
    Text,
    TouchableOpacity
} = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({
    getInitialState: function() {        return {};
    },
    componentDidMount: function() {
    },
    _pressButton: function() {        const { navigator } = this.props;        //或者写成 const navigator = this.props.navigator;
        //为何这里能够取得 props.navigator?请看上文:
        //<Component {...route.params} navigator={navigator} />
        //这里传递了navigator做为props
        if(navigator) {
            navigator.push({
                name: 'SecondPageComponent',
                component: SecondPageComponent,
            })
        }
    },
    render: function() {        return (
            <View>
                <TouchableOpacity onPress={this._pressButton}>
                    <Text>点我跳转</Text>
                </TouchableOpacity>
            </View>
        );
    }
});

这个里面建立了一个能够点击的区域,让咱们点击能够跳到SecondPageComponent这个页面,实现页面的跳转。 如今来建立SecondPageComponent,而且让它能够再跳回FirstPageComponent:

var {
    View,
    Text,
    TouchableOpacity,
} = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({
    getInitialState: function() {        return {};
    },
    componentDidMount: function() {
    },
    _pressButton: function() {        const { navigator } = this.props;        if(navigator) {            //很熟悉吧,入栈出栈~ 把当前的页面pop掉,这里就返回到了上一个页面:irstPageComponent了
            navigator.pop();
        }
    }
    render: function() {
        <View>
            <TouchableOpacity onPress={this._pressButton}>
                <Text>点我跳回去</Text>
            </TouchableOpacity>
        </View>
    }
});

大功告成,能进能出了。

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

getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些jumpBack() - 跳回以前的路由,固然前提是保留如今的,还能够再跳回来,会给你保留原样。jumpForward() - 上一个方法不是调到以前的路由了么,用这个跳回来就行了jumpTo(route) - Transition to an existing scene without unmountingpush(route) - Navigate forward to a new scene, squashing any scenes that you could jumpForward topop() - Transition back and unmount the current scenereplace(route) - Replace the current scene with a new routereplaceAtIndex(route, index) - Replace a scene as specified by an indexreplacePrevious(route) - Replace the previous sceneimmediatelyResetRouteStack(routeStack) - Reset every scene with an array of routespopToRoute(route) - Pop to a particular scene, as specified by its route. All scenes after it will be unmountedpopToTop() - 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 = {
    name: 'LoginComponent',
    component: LoginComponent,
}

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

而后下面要讨论,怎么传递参数过去,或者从对方获取参数。 传递参数,经过push就能够了。 好比在一个 press的事件里:

//FirstPageComponent.jsvar {
       View,
        Text,
    TouchableOpacity
} = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({
    getInitialState: function() {        return {
            id: 2,
        };
    },
    componentDidMount: function() {
    },
    _pressButton: function() {        const { navigator } = this.props;        if(navigator) {
            navigator.push({
                name: 'SecondPageComponent',
                component: SecondPageComponent,                //这里多出了一个 params 其实来自于<Navigator 里的一个方法的参数...
                params: {
                    id: this.state.id
                }
            });
        }
    }
    render: function() {        return (
            <View>
                <TouchableOpacity onPress={this._pressButton}>
                    <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.jsvar {
    View,
    Text,
    TouchableOpacity,
} = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({
    getInitialState: function() {        return {
            id: null
        };
    },
    componentDidMount: function() {        //这里获取从FirstPageComponent传递过来的参数: id
        this.setState({
            id: this.props.id
        });
    },
    _pressButton: function() {        const { navigator } = this.props;        if(navigator) {
            navigator.pop();
        }
    }
    render: function() {        return (
            <View>
                <Text>得到的参数: id={ this.state.id }</Text>
                <TouchableOpacity onPress={this._pressButton}>
                    <Text>点我跳回去</Text>
                </TouchableOpacity>
            </View>
        );
    }
});

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

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

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

//FirstPageComponent.jsvar {
       View,
        Text,
    TouchableOpacity
} = React;var SecondPageComponent = require('./SecondPageComponent');var FirstPageComponent = React.create({
    getInitialState: function() {        return {
            id: 2,
            user: null,
        };
    },
    componentDidMount: function() {
    },
    _pressButton: function() {        var _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: function() {        if( this.state.user ) {            return(
                <View>
                    <Text>用户信息: { JSON.stringify(this.state.user) }</Text>
                </View>
            );
        }else {            return(
                <View>
                    <TouchableOpacity onPress={this._pressButton}>
                        <Text>查询ID为{ this.state.id }的用户信息</Text>
                    </TouchableOpacity>
                </View>
            );
        }

    }
});

而后再操做SecondPageComponent:

//SecondPageComponent.jsUSER_MODELS = {    1: { name: 'mot', age: 23 },    2: { name: '晴明大大', age: 25 }
};var {
    View,
    Text,
    TouchableOpacity,
} = React;var FirstPageComponent = require('./FirstPageComponent');var SecondPageComponent = React.create({
    getInitialState: function() {        return {
            id: null
        };
    },
    componentDidMount: function() {        //这里获取从FirstPageComponent传递过来的参数: id
        this.setState({
            id: this.props.id
        });
    },
    _pressButton: function() {        const { navigator } = this.props;        if(this.props.getUser) {            var user = USER_MODELS[this.props.id];            this.props.getUser(user);
        }        if(navigator) {
            navigator.pop();
        }
    }
    render: function() {        return(
            <View>
                <Text>得到的参数: id={ this.state.id }</Text>
                <TouchableOpacity onPress={this._pressButton}>
                    <Text>点我跳回去</Text>
                </TouchableOpacity>
            </View>
          );
    }
});

看下效果如何吧。

下面还有Navigator配合TabBarIOS的用法:

相关文章
相关标签/搜索