初始ReactNative中的路由

基础页面跳转

路由跳转(navigation)

  1. function DetailsScreen({ navigation }) {
  2. return (
  3. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  4. <Text>Details Screen</Text>
  5. <Button
  6. title="Go to Details... again"
  7. onPress={() => navigation.navigate('Details')}
  8. />
  9. </View>
  10. );
  11. }

路由跳转(push)

  1. <Button
  2. title="Go to Details... again"
  3. onPress={() => navigation.push('Details')}
  4. />

注意navigationpush的区别 Each time you call push we add a new route to the navigation stack. When you call navigate it first tries to find an existing route with that name, and only pushes a new route if there isn’t yet one on the stack.

路由回退(goBack)

  1. function DetailsScreen({ navigation }) {
  2. return (
  3. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  4. <Text>Details Screen</Text>
  5. <Button
  6. title="Go to Details... again"
  7. onPress={() => navigation.push('Details')}
  8. />
  9. <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
  10. <Button title="Go back" onPress={() => navigation.goBack()} />
  11. </View>
  12. );
  13. }

回退多屏(popToTop)

popToTop是直接返回当前页面展栈中的最顶层 如果想要回退到指定的页面,需要使用navigate

  1. function DetailsScreen({ navigation }) {
  2. return (
  3. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  4. <Text>Details Screen</Text>
  5. <Button
  6. title="Go to Details... again"
  7. onPress={() => navigation.push('Details')}
  8. />
  9. <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
  10. <Button title="Go back" onPress={() => navigation.goBack()} />
  11. <Button
  12. title="Go back to first screen in stack"
  13. onPress={() => navigation.popToTop()}
  14. />
  15. </View>
  16. );
  17. }
  • navigation.navigate(‘RouteName’) 推送一个新的路由到本地堆栈导航器,如果它还没有在堆栈中,否则它会跳到该屏幕。
  • 我们可以随意调用navigation.push(‘RouteName’),它将继续推送路由。
  • 标题栏会自动显示一个返回按钮,但你可以通过调用navigation.goBack()以编程方式返回。在Android上,硬件的返回按钮就像预期的那样。
  • 你可以通过navigation.navigate(‘RouteName’)回到堆栈中的一个现有屏幕,你也可以通过navigation.popToTop()回到堆栈中的第一个屏幕。
  • 导航道具对所有屏幕组件(在路由配置中定义为屏幕并被React Navigation渲染为路由的组件)都可用。

页面传参

假定参数为params, 那么一般通过navigation.navigate(path, params)来在页面跳转的时候传递参数

  1. function HomeScreen({ navigation }) {
  2. return (
  3. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  4. <Text>Home Screen</Text>
  5. <Button
  6. title="Go to Details"
  7. onPress={() => {
  8. /* 1. Navigate to the Details route with params */
  9. navigation.navigate('Details', {
  10. itemId: 86,
  11. otherParam: 'anything you want here',
  12. });
  13. }}
  14. />
  15. </View>
  16. );
  17. }
  18. function DetailsScreen({ route, navigation }) {
  19. /* 2. Get the param */
  20. const { itemId, otherParam } = route.params;
  21. return (
  22. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  23. <Text>Details Screen</Text>
  24. <Text>itemId: {JSON.stringify(itemId)}</Text>
  25. <Text>otherParam: {JSON.stringify(otherParam)}</Text>
  26. <Button
  27. title="Go to Details... again"
  28. onPress={() =>
  29. navigation.push('Details', {
  30. itemId: Math.floor(Math.random() * 100),
  31. })
  32. }
  33. />
  34. <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
  35. <Button title="Go back" onPress={() => navigation.goBack()} />
  36. </View>
  37. );
  38. }

props中可以结构出route对象,route对象包含了当前页面的一些信息,比如nameparam等等 image.pngparams中我们可以拿到传递的参数

在界面中,我们对传递过来的参数进行更新,就像更新自身的状态一样:

  1. navigation.setParams({
  2. query: 'someText',
  3. });

也可以在路由配置中给界面添加默认的参数,如下所示:

  1. <Stack.Screen
  2. name="Details"
  3. component={DetailsScreen}
  4. initialParams={{ itemId: 42 }}
  5. />
  • 如果导航到某个界面时没有指定任何的参数,那么就会使用默认的参数
  • 默认参数也会和传递的参数进行浅层次合并

除了可以从其他界面接收参数以外,我们还可以向之前的界面传递参数。比如我们在首页点击登录,一般会跳转到另外一个专门的页面进行信息的填写,而当我们登录完毕后,可以将登陆成功的信息返回给首页。
这一般使用的是navigation.navigate()

  1. function HomeScreen({ navigation, route }) {
  2. React.useEffect(() => {
  3. if (route.params?.post) {
  4. // Post updated, do something with `route.params.post`
  5. // For example, send the post to the server
  6. }
  7. }, [route.params?.post]);
  8. return (
  9. <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
  10. <Button
  11. title="Create post"
  12. onPress={() => navigation.navigate('CreatePost')}
  13. />
  14. <Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
  15. </View>
  16. );
  17. }
  18. function CreatePostScreen({ navigation, route }) {
  19. const [postText, setPostText] = React.useState('');
  20. return (
  21. <>
  22. <TextInput
  23. multiline
  24. placeholder="What's on your mind?"
  25. style={{ height: 200, padding: 10, backgroundColor: 'white' }}
  26. value={postText}
  27. onChangeText={setPostText}
  28. />
  29. <Button
  30. title="Done"
  31. onPress={() => {
  32. // Pass and merge params back to home screen
  33. navigation.navigate({
  34. name: 'Home',
  35. params: { post: postText },
  36. merge: true,
  37. });
  38. }}
  39. />
  40. </>
  41. );
  42. }

在路由传递参数的过程中,我们需要有一种传递参数的规范,哪些数据可以放在路由参数中,而哪些不建议放在里面。

简单来讲,我们只需要传递最核心、最重要的那个数据,这个数据的地位可以类比成数据库中的主键那样,可以唯一确定一条数据。比如,我们需要传递的应该是用户id而不是用户的全部信息,用户的全部信息应该放在一种全局存储中。

比如我们现在需要跳转到用户个人资料界面,很多人可能直接传递下面这种参数:

  1. // Don't do this
  2. navigation.navigate('Profile', {
  3. user: {
  4. id: 'jane',
  5. firstName: 'Jane',
  6. lastName: 'Done',
  7. age: 25,
  8. },
  9. });

但事实上,并不推荐这么做,这可能导致在界面上显示的是过时的数据,正确的做法应该是只传入用户的编号,而具体数据通过后续查询来得到:

  1. navigation.navigate('Profile', { userId: 'jane' });
  • navigate和push接受一个可选的第二个参数,让你向你正在导航的路由传递参数。例如navigation.navigate(‘RouteName’, { paramName: ‘value’ }) 。
  • 你可以在一个屏幕内通过route.params读取参数
  • 你可以通过 navigation.setParams 来更新屏幕的参数
  • 初始参数可以通过屏幕上的initialParams来进行传递。
  • 参数应该包含显示屏幕所需的最小数据,而不是更多