RN 版本:0.50
操作环境:Windows 10
React Navigation 版本:1.0.0-beta.20
之前已经说过,每个在 navigator 中注册过的页面都会接受一个 navigation 属性,它包含以下几属性:
navigate
- (helper) 连接其他页面state
- 页面当前的状态/路由setParams
- (helper) 更新路由的参数goBack
- (helper) 关闭当前活动页面并返回dispatch
- 给路由器发送指令行为
在之前的几篇文章中,我们已经接触过 navigate
(用来@R_452_404@面)、state
(用来获取传递的参数)和 setParams
(用来改变参数),这篇文章将会对它们进行更详细的说明。
注意:navigation
属性被传递给了每一个导航相关组件并且包括导航器。不过需要注意的不同点是导航器 navigator 的 navigation
属性不会包含那些 helper 类的函数(navigate
,goBack
等),它只有 state
和 dispatch
属性。如果你想要使用导航器 navigation
属性中的 navigate
函数,你必须使用 dispatch
来传递一个导航操作意图(关于 Navigation Actions 下一篇文章会讲)。
与 Redux 集成时的注意事项
注:这段文字直接翻译自官方文档,由于我还没有了解过 redux,所以看得不是太懂。有兴趣的可以看看 原文。
由于许多人对 navigator 顶级 API 的理解错误,他们并不能很好地正确使用 navigation 属性与 redux 的关联。导航器 navigator 如果没有接收到 navigation 属性话它会保持自己的状态,但这个并不是你通常情况下关联 redux 时想要的特征。对于嵌套在主导航器里面的各个导航器,你总是会想把 navigation 属性传递下去。这就允许你的顶级导航器去传达并给子导航器提供状态。这个时候你只需要将顶级路由与 redux 集成,因为其他的路由都被包含在了它的里面。
navigate - 链接其他屏幕
navigate(routeName,params,action)
routeName
- 在你的 app 中已经注册过的打算跳转的目的路由名称params
- 传给目的路由的参数action
- (高级)如果屏幕是导航器,则在子路由中运行的操作。有关支持的操作的完整列表,请参阅 操作文档,暂时打算下一篇文章再介绍。
class HomeScreen extends React.Component {
render() {
const {navigate} = this.props.navigation;
return (
<View>
<Text>This is the home screen of the app</Text>
<Button
// 跳转到 Profile 页面并传递参数 name
onPress={() => navigate('Profile',{name: 'Brent'})}
title="Go to Brent's profile"
/>
</View>
)
}
}
state - 屏幕当前状态/路由
一个屏幕可以通过 this.props.navigation.state
获取它的路由,它返回的是一个如下类型的对象:
{
// the name of the route config in the router
// 路由器中设置的路由名称
routeName: 'Profile',// a unique identifier used to sort routes
// 为方便管理路由而产生的唯一标识
key: 'main0',// an optional object of string options for this screen
// 给当前屏幕可供选择的参数对象
params: { hello: 'world' }
}
class ProfileScreen extends React.Component {
render() {
const {state} = this.props.navigation;
// state.routeName === 'Profile'
return (
// 获取参数 name,我们之前已经见到过这种用法了
<Text>Name: {state.params.name}</Text>
);
}
}
setParams - 改变路由参数
触发 setParams
方法允许页面改变路由中的参数,这对于更新头部标题及按钮很有用处。上一篇文章中我们曾经介绍过这个方法。
class ProfileScreen extends React.Component {
render() {
const {setParams} = this.props.navigation;
return (
<Button
onPress={() => setParams({name: 'Lucy'})}
title="Set title name to 'Lucy'"
/>
)
}
}
goBack - 关闭当前活动页面并返回
给该方法提供一个 key,来决定要从哪个路由返回(即要关闭哪个页面)。默认情况下,会关闭掉调用该方法的当前路由。如果目标是想要回到 anywhere 而不具体地说明要关闭哪个页面,可以调用 goBack(null)
。
class HomeScreen extends React.Component {
render() {
const {goBack} = this.props.navigation;
return (
<View>
<Button
// 关闭当前的 HomeScreen
onPress={() => goBack()}
title="Go back from this HomeScreen"
/>
<Button
// 这里测试的结果也是关闭了当前的 HomeScreen
onPress={() => goBack(null)}
title="Go back anywhere"
/>
<Button
// 关闭从 'screen-123' 到栈顶的所有路由
onPress={() => goBack('screen-123')}
title="Go back from screen-123"
/>
</View>
)
}
}
从指定的页面返回
假设我们有四个路由 A B C D 依次入栈:
navigation.navigate(SCREEN_KEY_A);
...
navigation.navigate(SCREEN_KEY_B);
...
navigation.navigate(SCREEN_KEY_C);
...
navigation.navigate(SCREEN_KEY_D);
假如你在 screen D 并且想要返回到 screen A(关闭 D,C 和 B),那么你就需要这么写:
// will go to screen A FROM screen B
navigation.goBack(SCREEN_KEY_B)
注意:这个方法里面的 key 值,并不是定义 navigator 时我们给页面自定义的 key,而是上面 state 里面的 state.key
。并且我们在 D 中不能直接通过 this.props.navigation.state.key
来获取,因为它获取的是 D 的 key,所以我们要在 B 中获取到它,然后一级一级的传递给 D,最后调用 navigation.goBack(SCREEN_KEY_B)
来回到 A。
dispatch - 给路由发送一个行为
使用 dispatch 给路由指派任意的 navigation 行为,其它的 navigation 函数使用后台的 dispatch 来实现。记住如果你想指派 react-navigation 行为的话,你应该使用库里提供的 action creators。查看 Navigation Actions 来获取完整的可指派行为(具体行为会在下一篇文章进行说明)。
import { NavigationActions } from 'react-navigation'
const navigateAction = NavigationActions.navigate({
routeName: 'Profile',params: {},// navigate can have a nested navigate action that will be run inside the child router
// navigate 可以嵌套 navigate action,它会在子路由里面执行
action: NavigationActions.navigate({ routeName: 'SubProfileRoute'})
})
this.props.navigation.dispatch(navigateAction)
@H_44_301@