基础篇章:关于 React Native 之 Navigator 组件的讲解

今天我们来讲讲Navigator这个小家伙,呃……不能说小家伙,因为它还是很厉害的,有了它我就就能实现各个界面的跳转和切换。所以它的名字叫导航器。来,今天我们就一起来学习学习它。

使用我Navigator可以让你们实现在应用内不同页面的切换,我是用JavaScript实现的,而且我有两个:IOS和Android,如果在IOS上使用请用我的双胞胎兄弟NavigatorIOS,因为它充分利用本地的UIKit导航。

要想设置Navigator,使用我,你们必须确定一个或多个调用routes对象,去定义每个场景。你们还可以利用renderScene方法,导航栏可以根据指定的路由来渲染场景。

官网基础小例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
render() {
const routes = [
{title: 'First Scene', index: 0},
{title: 'Second Scene', index: 1},
];
return (
<Navigator
initialRoute={routes[0]}
initialRouteStack={routes}
renderScene={(route, navigator) =>
<TouchableHighlight onPress={() => {
if (route.index === 0) {
navigator.push(routes[1]);
} else {
navigator.pop();
}
}}>
<Text>Hello {route.title}!</Text>
</TouchableHighlight>
}
style={{padding: 100}}
/>
);
}

nitialRoute
在上面的示例中,initialRoute 用于指定的第一个路由。它包含一个标题属性,标识路由。RenderScene 属性返回一个函数,显示路由标题文本。
initialRouteStack
initialRoute指定第一个显示的页面,而要设置多个场景,你们通过initialRouteStack属性了。通过上面例子,我们可以看到定义了两个路由,而且每个路由都有一个用于管理被渲染场景的索引属性。在renderScene方法中有一个触摸事件,触摸决定导航器是推或者弹出哪个导航场景。

我们可以在Navigator上设置标题导航栏Navigation Bar,在标题导航栏中我们可以通过routeMapper属性去设置左,右和标题导航栏。在配置左,右,和标题导航栏项目,您可以访问信息,如当前路由对象和导航状态。这使您可以为每个场景自定义标题以及按钮。例如,您可以选择隐藏场景中的左键。
例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Navigator
renderScene={(route, navigator) =>
// ...
}
navigationBar={
<Navigator.NavigationBar
routeMapper={{
LeftButton: (route, navigator, index, navState) =>
{ return (<Text>Cancel</Text>); },
RightButton: (route, navigator, index, navState) =>
{ return (<Text>Done</Text>); },
Title: (route, navigator, index, navState) =>
{ return (<Text>Awesome Nav Bar</Text>); },
}}
style={{backgroundColor: 'gray'}}
/>
}
/>

场景转换

要想改变场景的动画和转换,相当于我们Android中的进场和转场动画,我们可以通过configureScene属性来获得对于给定路线的配置对象。如下:

1
2
3
4
5
6
7
<Navigator
renderScene={(route, navigator) =>
// ...
}
configureScene={(route, routeStack) =>
Navigator.SceneConfigs.FloatFromBottom}
/>

属性

  • configureScene function 就是通过它配置场景转换的。它有如下属性:
    • Navigator.SceneConfigs.PushFromRight (default)
    • Navigator.SceneConfigs.FloatFromRight
    • Navigator.SceneConfigs.FloatFromLeft
    • Navigator.SceneConfigs.FloatFromBottom
    • Navigator.SceneConfigs.FloatFromBottomAndroid
    • Navigator.SceneConfigs.FadeAndroid
    • Navigator.SceneConfigs.HorizontalSwipeJump
    • Navigator.SceneConfigs.HorizontalSwipeJumpFromRight
    • Navigator.SceneConfigs.VerticalUpSwipeJump
    • Navigator.SceneConfigs.VerticalDownSwipeJump
  • initialRoute object 定义启动时加载的路由。路由是导航栏用来识别渲染场景的一个对象。initialRoute必须是initialRouteStack中的一个路由。initialRoute默认为initialRouteStack中最后一项。
  • initialRouteStack [object] 存放路由的一个数组
  • navigationBar node 上面介绍了
  • navigator object
  • onDidFocus function 每当导航切换完成或初始化之后,调用此回调,参数为新场景的路由
  • onWillFocus function 会在导航切换之前调用,参数为目标路由
  • renderScene function 用来渲染每一个路由指定的页面
  • sceneStyle 样式风格

方法

  • immediatelyResetRouteStack(nextRouteStack) 用新的路由数组来重置路由栈
  • jumpTo(route) 跳转到传入的已有的场景并且不卸载
  • jumpForward(0) 跳转到下一个场景
  • jumpBack(0) 同上相反的意思
  • push(route) 跳转到新的场景,并且将场景入栈,你可以稍后用jump forward 跳转回去
  • popN(n) 回到ñ场景一次。当N = 1,行为相匹配pop()方法。当N是无效的(负或大于当前的路线计算),什么也不做。
  • pop(0) 跳转回去并且卸载掉当前场景
  • replaceAtIndex(route, index, cb) 替换掉指定序列的路由场景
  • replace(route) 用一个新路由替换当前场景
  • replacePrevious(route) 替换掉之前的场景
  • popToTop(0) pop到栈中的第一个场景,卸载掉所有的其他场景
  • popToRoute(route) pop到路由指定的场景,在整个路由栈中,处于指定场景之后的场景将会被卸载
  • replacePreviousAndPop(route) 取代之前的场景,并弹出它
  • resetTo(route) 跳转到指定的新场景,并重置路由栈
  • getCurrentRoutes() 获取当前栈里的路由

实例

效果图


怎么样?我的样子很帅吧,是不是很想和我玩,那就赶紧行动起来吧,我已经迫不及待的想跟你们一起玩了。来看看怎么和我玩的实例代码吧。

代码

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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
Navigator,
Image,
TouchableHighlight,
TouchableOpacity,
View
} from 'react-native';
NavigationBarRouteMapper = {
LeftButton(route, navigator, index, navState) {
if (route.id === 'first') {
return null;
}
previousRoute = navState.routeStack[index - 1];
return (
<TouchableOpacity
onPress={() => navigator.pop()}
style={styles.navBarLeftButton}>
<Image source={require('./back.png')} style={styles.backImage}>
</Image>
</TouchableOpacity>
);
},
RightButton(route, navigator, index, navState) {
if (route.id === 'second') {
return null;
}
return (
<TouchableOpacity
onPress={() => navigator.push({id:'second',title:'第二页',data:"我是从第一页跳转过来的"})}
style={styles.navBarRightButton}>
<Text style={[styles.navBarButtonText]}>
下一页
</Text>
</TouchableOpacity>
);
},
Title(route, navigator, index, navState) {
return (
<Text style={[styles.navBarTitleText]}>
{route.title}
</Text>
);
},
};
export default class NavigatorDemo extends Component {
render(){
return (
<Navigator
style = {styles.container}
initialRoute={{id:"first",title:"第一页"}}
renderScene={this.renderNav}
configureScene={(route, routeStack) => Navigator.SceneConfigs.HorizontalSwipeJump}
navigationBar={
<Navigator.NavigationBar
routeMapper={NavigationBarRouteMapper}
style={{backgroundColor:'white'}}
/>
}
/>
);
}
renderNav(route,nav){
switch (route.id) {
case 'first':
return <FirstScreen navigator={nav} title="第一页"/ >;
case 'second':
return (<SecondScreen navigator={nav} title="第二页" data={route.data}/>);
}
}
}
class FirstScreen extends Component{
toSecond=()=>{
this.props.navigator.push({id:"second",title:"第二页",data:"我是第二页"});
}
render(){
return (
<View style={styles.firstView}>
<TouchableHighlight
style={{padding:10}}
onPress={this.toSecond}
underlayColor="blue">
<Text style={styles.contentText}>第一页</Text>
</TouchableHighlight>
</View>
);
}
}
class SecondScreen extends Component{
toFirst=()=>{
this.props.navigator.pop();
}
render(){
return (
<View style={styles.secondView}>
<TouchableHighlight
style={{padding:10}}
onPress={this.toFirst}
underlayColor="red">
<Text style={styles.contentText}>{this.props.data}</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
backImage:{
width:15,
height:30,
},
navBarTitleText: {
color: 'black',
fontWeight: '500',
marginTop:20,
},
navBarLeftButton: {
paddingLeft: 10,
paddingTop:15,
},
navBarRightButton: {
paddingRight: 10,
paddingTop:20,
},
navBarButtonText: {
color: '#5890FF',
},
container: {
flex: 1,
},
firstView:{
flex: 1,
backgroundColor:'red',
justifyContent: 'center',
},
secondView:{
flex:1,
justifyContent: 'center',
backgroundColor:'blue',
},
contentText:{
fontSize:22,
color:'white',
textAlign:'center',
},
});
AppRegistry.registerComponent('NavigatorDemo', () => NavigatorDemo);
loonggg wechat
欢迎您扫一扫上面的二维码,订阅我的微信公众号「 非著名程序员」!
坚持原创技术分享,您的支持将鼓励我继续创作!