ReactNative页面跳转Navigator
Navigator即导航器,通过导航器我们可以实现应用在不同的页面之间进行跳转。
导航器会建立一个路由栈,用来弹出,推入或者替换路由状态。该路由栈相当于android原生中使用的任务栈。
renderScene
该方法就相当于我们使用的startActivity方法了,我们可以在该方法中设置需要渲染的场景(跳转的页面),该方法接收两个参数(必要参数),route和navigator,其中route就是路由的页面,navigator是一个Navigator对象,因为Navigator对象拥有pop,push,jump等方法,我们需要导航器对象来实现页面的跳转。而路由route需要我们提前进行配置。
我们来看一下renderScene的使用:
renderScene={(route, navigator) => {
let Component = route.component;
return <Component {...route.params} navigator={navigator} />
}}
- 1
- 2
- 3
- 4
通过上面的方法来实现页面的跳转,同时将导航器作为属性进行传递过去。之前说过,route需要进行配置,通过initialRoute方法来对我们的路由进行初始化,
如下所示:
initialRoute={{ name: defaultName, component: defaultComponent }}
- 1
initialRoute是一个对象,我们通过给对象设置名称和对应的组件完成route的初始化,即只要传入需要跳转的组件的名称和组建对象,即可在renderScene中完成页面的跳转。
再回头看renderScene方法,route参数就是我们通过initialRoute初始化的对象,我们通过route.component即可获得我们需要渲染(即跳转到)的对象,然后在return的时候返回这个对象完成页面的跳转。为了防止出现问题,我们加上route.component为空的判断,如果不为空,再进行渲染。
renderScene={(route, navigator) => {
let Component = route.component;
if(route.component){
return <Component {...route.params} navigator={navigator} />
}
}}
- 1
- 2
- 3
- 4
- 5
- 6
configureScene
该方法用来设置指定路由对象的配置信息,从而改变场景的动画或者手势。
configureScene={(route) => {
//跳转的动画
return Navigator.SceneConfigs.VerticalDownSwipeJump;
}}
- 1
- 2
- 3
- 4
例如通过如下的方法我们就可以对我们即将要跳转的界面设置跳转动画。
Navigator.SceneConfigs为我们提供了大量的跳转动画,具体可以参考如下文件。
MyProject\node_modules\react-native\Libraries\CustomComponents\Navigator\NavigatorSceneConfigs.js
这样我们就完成了在程序默认页面到我们自定义页面之间的跳转过程。
完整代码如下所示:
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
Image,
TextInput,
View,
Navigator
} from 'react-native';
import FirstPageComponent from './app/src/FirstPageComponent';
export default class MyProject extends React.Component {
render() {
var defaultName = 'FirstPageComponent';
var defaultComponent = FirstPageComponent;
return (
<Navigator
//指定了默认的页面,也就是启动app之后会看到的第一屏,需要两个参数,name跟component
initialRoute={{ name: defaultName, component: defaultComponent }}
configureScene={(route) => {
//跳转的动画
return Navigator.SceneConfigs.FadeAndroid;
}}
renderScene={(route, navigator) => {
let Component = route.component;
if(route.component){
return <Component navigator={navigator} />
}
}} />
);
}
}
AppRegistry.registerComponent('MyProject', () => MyProject);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
其中FirstPageComponent是我们自定义的一个组件,没有添加功能,只放了一个Text,如下所示:
import React,{
View,
Text,
} from 'react-native';
export default class FirstPageComponent extends React.Component{
constructor(props){
super(props);
this.state = {};
}
render(){
return (
<View>
<Text>我是默认页面</Text>
</View>
);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
如果我们现在想要实现一个从FirstPageComponent到另一个页面之间的跳转,那我们需要怎么做呢?
因为我们之前在页面跳转的时候将导航器对象作为属性传递给了我们的FirstPageComponent,那么我们此时就可以获取这个navigator对象,navigator中有很多方法可以供我们调用进行导航。
首先我们给创建一个可点击的区域包裹Text,这样点击Text就可以触发事件,如下所示,改造render,
render() {
return (
<View>
<TouchableOpacity onPress={this._pressButton.bind(this)}>
<Text>点我跳转</Text>
</TouchableOpacity>
</View>
);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们先不关注TouchableOpacity是什么,只知道他是一片可点击的区域,并且拥有点击事件即可。
然后我们实现_pressButton方法,如下所示:
_pressButtoon(){
const { navigator} = this.props;
if (navigator) {
navigator.push({
name:'SecondPageComonent',
component:SecondPageComonent,
})
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
我们从传递过来的属性中获取navigator,然后调用navigator的push方法,push方法接收的参数为route对象,我们定义route对象的名称和组件对象,将其放入路由栈,这样我们通过操控路由栈的方式实现了另一个页面的跳转。
这样我们改造后的FirstPageComponent如下所示:
import React,{
View,
Text,
TouchableOpacity
} from 'react-native';
import SecondPageComonent from "./SecondPageComponent";
export default class FirstPageComponent extends React.Component{
constructor(props){
super(props);
this.state = {};
}
_pressButtoon(){
const { navigator} = this.props;
if (navigator) {
navigator.push({
name:'SecondPageComonent',
component:SecondPageComonent,
})
}
}
render(){
return (
<View>
<TouchableOpacity onPress={this._pressButtoon.bind(this)}>
<Text>点我跳转</Text>
</TouchableOpacity>
</View>
);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
其中SecondPageComonent是我们定义的另一个组件,实现代码如下所示:
import React,{
View,
Text,
TouchableOpacity,
} 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){
navigator.pop();
}
}
render(){
return (
<View>
<TouchableOpacity onPress={this._pressButton.bind(this)}>
<Text>点我跳转回去</Text>
</TouchableOpacity>
</View>
);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
在SecondPageComponent中,我们通过控制路由栈将页面出栈的方式pop()完成跳转回到第一个页面的功能。
我们发现,页面的跳转都是通过navigator对象的一系列方法通过对路由栈的操控来实现页面之间跳转加载的功能的,我们看一下导航器都有那些方法:
getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些。
jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。
jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了。
jumpTo(route) - 跳转到已有的场景并且不卸载。
push(route) - 跳转到新的场景,并且将场景入栈,你可以稍后跳转过去
pop() - 跳转回去并且卸载掉当前场景
replace(route) - 用一个新的路由替换掉当前场景
replaceAtIndex(route, index) - 替换掉指定序列的路由场景
replacePrevious(route) - 替换掉之前的场景
immediatelyResetRouteStack(routeStack) - 用新的路由数组来重置路由栈
popToRoute(route) - pop到路由指定的场景,其他的场景将会卸载。
popToTop() - pop到栈中的第一个场景,卸载掉所有的其他场景。
参数的传递
当我们从一个页面跳转到另一个页面的时候,总免不了需要进行参数的传递,那么我们怎么将参数传递到另一个页面呢?
我们可以通过push()方法将参数传递过去。
首先我们需要明确FirstPageComponent,MyProject和SecondPageComponent三者之间的关系,程序启动时首先会启动MyProject,然后看到在MyProject中有一个导航器,该导航器初始化路由的时候获取了我们的FirstPageComponent,将其解析为一个组件在renderScene的时候将其加载到页面上。我们再来看一下导航器加载的方法:
renderScene={(route, navigator) => {
let Component = route.component;
if(route.component){
return <Component navigator={navigator} />
}
}}
- 1
- 2
- 3
- 4
- 5
- 6
我们所有的组件都是通过导航器加载到页面上的,第一个页面是,第二个页面并不是由第一个页面启动的,而是有导航器控制路由栈来显示在页面上的,我们在renderScene是获取到第一个页面,并且将其渲染到屏幕上,我们在第一个页面中设置的push信息也是将信息传递给导航器的,那么我们就可以在这个时候将需要传递给Navigator,然后让其在传递给第二个页面,这样就可以完成参数的传递。
首先我们更改FirstPageComponent的按钮点击事件,如下所示:
navigator.push({
name:'SecondPageComonent',
component:SecondPageComonent,
params:{
message:"I am from FirstPageComponent",
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
然后在Navigator中获取,如下所示:
renderScene={(route, navigator) => {
let Component = route.component;
if(route.component){
return <Component {...route.params} navigator={navigator} />
}
}}
- 1
- 2
- 3
- 4
- 5
- 6
在这里就相当于将参数传递给了Navigator,展开成然后我们就可以在第二个页面中通过props.message获取到信息,如下所示,添加页面挂载时的方法,设置状态的方法将获取到的参数保存在state中:
componentDidMount(){
this.setState({
message:this.props.message,
});
}
- 1
- 2
- 3
- 4
- 5
如果当我们返回的时候需要携带参数,我们可以通过给navigator设置一个回调方法,用于给第一个页面设置信息,这样就可以完成返回时数据的传递了。
完整代码如下所示:
index.android.js
'use strict';
import React, {
AppRegistry,
Component,
StyleSheet,
Text,
Image,
TextInput,
View,
Navigator
} from 'react-native';
import FirstPageComponent from './app/src/FirstPageComponent';
export default class MyProject extends React.Component {
render() {
var defaultName = 'FirstPageComponent';
var defaultComponent = FirstPageComponent;
return (
<Navigator
//指定了默认的页面,也就是启动app之后会看到的第一屏,需要两个参数,name跟component
initialRoute={{ name: defaultName, component: defaultComponent }}
configureScene={(route) => {
//跳转的动画
return Navigator.SceneConfigs.FadeAndroid;
}}
renderScene={(route, navigator) => {
let Component = route.component;
if(route.component){
return <Component {...route.params} navigator={navigator} />
}
}} />
);
}
}
AppRegistry.registerComponent('MyProject', () => MyProject);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
FirstPageComponent.js
import React,{
View,
Text,
TouchableOpacity
} from 'react-native';
import SecondPageComonent from "./SecondPageComponent";
export default class FirstPageComponent extends React.Component{
constructor(props){
super(props);
this.state = {
resultMessage:"hello",
};
}
_pressButtoon(){
var _this = this;
const { navigator} = this.props;
if (navigator) {
navigator.push({
name:'SecondPageComonent',
component:SecondPageComonent,
params:{
message:"I am from FirstPageComponent",
getResult:function(myMessage){
_this.setState({
resultMessage:myMessage,
})
}
}
})
}
}
render(){
return (
<View>
<TouchableOpacity onPress={this._pressButtoon.bind(this)}>
<Text>{this.state.resultMessage}</Text>
</TouchableOpacity>
</View>
);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
SecondPageComponent.js
import React,{
View,
Text,
TouchableOpacity,
} from 'react-native';
import FirstPageComponent from './FirstPageComponent';
export default class SecondPageComponent extends React.Component{
constructor(props){
super(props);
this.state = {
message:"",
};
}
componentDidMount(){
this.setState({
message:this.props.message,
});
}
_pressButton(){
const { navigator } = this.props;
if(this.props.getResult){
this.props.getResult("This is from SecondPageComponent");
}
if(navigator){
navigator.pop();
}
}
render(){
return (
<View>
<TouchableOpacity onPress={this._pressButton.bind(this)}>
<Text>{this.state.message}</Text>
</TouchableOpacity>
</View>
);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
最终效果如下所示: