在ReactNative开发中,目前为止,活动页面之间的跳转使用Navigator来实现。但是在实际使用中却有着不为人知的秘密......
基本概念
-
navigator
: 一个用来管理所有界面对象的栈,人称之 “路由栈”, 学名 “导航”。 -
route
: 路由栈里的每一个对象,称之为 “路由”,用来存储每一个页面组件以及一些需要传递给对应界面的props参数。
使用Navigator来导航整个App页面
在Android中,我们都知道管理Activity的Task栈。由此可知,我们需要把Navigator放在一个常驻的界面中。因此我们在这里放在整个ReactNative工程的入口——index.ios.js/index.android.js 中。
为项目添加Navigator控制
- 第一步需要做的依旧是引入Navigator组件 (以下React已import导入)
- 加入全局的名字空间以方便使用
let { Navigator } = React
- 或者以
React.Navigator
的方式直接使用
-
使用Navigator组件
-
initialRoute
: 初始路由,也就是我们需要在navigator栈底放置的路由,因为此时也是栈顶,因此也就是初始化整个App的首页。 -
configureScene
: 设置页面切换动画,具体的值大家可以在node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
源库中找到。或者直接在sublime Text 3 中使用命令command+p
命令,然后输入NavigatorSceneConfigs
进行文件搜索。笔者看了一下,大概有不到十种动画,这里就不做具体介绍了。 -
renderScene
: 渲染当前路由场景,也就是渲染栈顶路由。回调方法里一个参数是当前路由route,另一个是navigator 路由栈。这里需要细讲一下:-
route
: 路由里包含一个必要的component变量和一些可选的参数,而component则就是当前需要渲染的组件。其他的一些可选的参数也是以键值对的方式保存在route对象中,并在这里以属性的方式传递给对应的component组件中。 -
navigator
: 这是Navigator组件在本回调方法中的参数,也就是我们在前边提到的路由栈。会在每次渲染新route的时候以属性的形式传递给route中component的对象。它可以在对应的场景中做一些操作,这里我们给出官方的部分文档:
-
- getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些。
- jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。
- jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了。
- jumpTo(route) - 跳转到已有的场景并且不卸载。
- push(route) - 跳转到新的场景,并且将场景入栈,你可以稍后跳转过去
- pop() - 跳转回去并且卸载掉当前场景
- replace(route) - 用一个新的路由替换掉当前场景
- replaceAtIndex(route, index) - 替换掉指定序列的路由场景
- replacePrevious(route) - 替换掉之前的场景
- immediatelyResetRouteStack(routeStack) - 用新的路由数组来重置路由栈
- popToRoute(route) - pop到路由指定的场景,其他的场景将会卸载。
- popToTop() - pop到栈中的第一个场景,卸载掉所有的其他场景。
* `{...route}` 这是一句 es6 语法,表示将route中所有的键值对以属性赋值的方式展开,也就是`{name: 'pober', gender: 'man'}` 到 `name = 'pober' gender = 'man'`之间的转换。。
* `passProps` 这是一个我们自己定义的key,后边会提到。同样是可选的
- 在对应页面中使用navigator路由栈进行基本的操作
在上边也提到了navigator的一些列方法。这里我们核心介绍一下push和pop的操作。
-
push(route)
: 跳转到下一个场景同时将它入栈。我们看一下以下代码this.props.navigator.push({ component: NextPage, passProps: {name: 'pober'} // 传递的参数(可选),{}里都是键值对 ps: test是关键字 })
-
pop()
顾名思义就是一个对navigator栈弹栈的过程,这经常发生在中的Back事件中。
项目实战
这里我们只进行几个必要的操作
-
将上次的History页面抽取出一个单独的js文件,我们在这里叫做
History.js
,放在了js.core
文件夹下,并在index.ios.js中引入之。 -
然后在index.ios.js中按照以上步骤加入Navigator组建的使用,设置初始路由为History页面,如果此时运行的效果和之前一样的话,就算是OK啦...
-
接着我们开始利用Navigator进行页面跳转的实践吧~
创建一个新的页面,我们叫HelloWorld.js吧,然后在History页面导入之,然后进行路由跳转即可。
History 更改如下代码:
_renderItem (contentData, sectionID, highlightRow) {
return (
<TouchableHighlight
onPress = {() => this.props.navigator.push({
component: HelloWorld,
passProps: {geeker: 'pober'}
})}>
<View style={styles.itemContainer}>
<Text style={[styles.title]}>{contentData.title}</Text>
<Image source={{uri: contentData.uri}}
style={styles.thumbnail}/>
</View>
</TouchableHighlight>
)
}
其实也就是给外层的TouchableHighlight
添加一个点击事件,然后添加的代码和上个模块的push
操作一样。我们还加入了一个key为geeker的键值对,值是我的名字pober
。
- 此时,做完以上三点,已经能够从History页面跳转到HelloWorld页面了。接下来我们再做一个navigator栈的操作——
pop
很简单,这里我们直接在HelloWorld页面手动执行这个操作就可以了。其实,自带的右滑返回也是这个操作...
render () {
return (
<View style={styles.container}>
<TouchableOpacity onPress = {() => this.props.navigator.pop()}>
<Text>{this.props.geeker}</Text>
</TouchableOpacity>
</View>
)
}
这里是HelloWorld的核心代码,我们使用了一个按钮,然后上边显示了我们在上一个界面中传入的geeker
变量,值当然就是伦家的名字pober
啦...点击之后,我们很简单地调用了navigator的pop()
方法。
HelloWorld
页面截图:
结语
路漫漫其修远兮,吾将上下而求索