初始ReactNative中的路由
基础页面跳转
路由跳转(navigation)
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
路由跳转(push)
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
注意
navigation
和push
的区别 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)
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
回退多屏(popToTop)
popToTop
是直接返回当前页面展栈中的最顶层 如果想要回退到指定的页面,需要使用navigate
function DetailsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Button
title="Go to Details... again"
onPress={() => navigation.push('Details')}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
<Button
title="Go back to first screen in stack"
onPress={() => navigation.popToTop()}
/>
</View>
);
}
- navigation.navigate(‘RouteName’) 推送一个新的路由到本地堆栈导航器,如果它还没有在堆栈中,否则它会跳到该屏幕。
- 我们可以随意调用navigation.push(‘RouteName’),它将继续推送路由。
- 标题栏会自动显示一个返回按钮,但你可以通过调用navigation.goBack()以编程方式返回。在Android上,硬件的返回按钮就像预期的那样。
- 你可以通过navigation.navigate(‘RouteName’)回到堆栈中的一个现有屏幕,你也可以通过navigation.popToTop()回到堆栈中的第一个屏幕。
- 导航道具对所有屏幕组件(在路由配置中定义为屏幕并被React Navigation渲染为路由的组件)都可用。
页面传参
假定参数为
params
, 那么一般通过navigation.navigate(path, params)
来在页面跳转的时候传递参数
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => {
/* 1. Navigate to the Details route with params */
navigation.navigate('Details', {
itemId: 86,
otherParam: 'anything you want here',
});
}}
/>
</View>
);
}
function DetailsScreen({ route, navigation }) {
/* 2. Get the param */
const { itemId, otherParam } = route.params;
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
<Text>itemId: {JSON.stringify(itemId)}</Text>
<Text>otherParam: {JSON.stringify(otherParam)}</Text>
<Button
title="Go to Details... again"
onPress={() =>
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
}
/>
<Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}
在
props
中可以结构出route
对象,route对象包含了当前页面的一些信息,比如name
,param
等等 在params
中我们可以拿到传递的参数
在界面中,我们对传递过来的参数进行更新,就像更新自身的状态一样:
navigation.setParams({
query: 'someText',
});
也可以在路由配置中给界面添加默认的参数,如下所示:
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
- 如果导航到某个界面时没有指定任何的参数,那么就会使用默认的参数
- 默认参数也会和传递的参数进行浅层次合并
除了可以从其他界面接收参数以外,我们还可以向之前的界面传递参数。比如我们在首页点击登录,一般会跳转到另外一个专门的页面进行信息的填写,而当我们登录完毕后,可以将登陆成功的信息返回给首页。
这一般使用的是navigation.navigate()
function HomeScreen({ navigation, route }) {
React.useEffect(() => {
if (route.params?.post) {
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
title="Create post"
onPress={() => navigation.navigate('CreatePost')}
/>
<Text style={{ margin: 10 }}>Post: {route.params?.post}</Text>
</View>
);
}
function CreatePostScreen({ navigation, route }) {
const [postText, setPostText] = React.useState('');
return (
<>
<TextInput
multiline
placeholder="What's on your mind?"
style={{ height: 200, padding: 10, backgroundColor: 'white' }}
value={postText}
onChangeText={setPostText}
/>
<Button
title="Done"
onPress={() => {
// Pass and merge params back to home screen
navigation.navigate({
name: 'Home',
params: { post: postText },
merge: true,
});
}}
/>
</>
);
}
在路由传递参数的过程中,我们需要有一种传递参数的规范,哪些数据可以放在路由参数中,而哪些不建议放在里面。
简单来讲,我们只需要传递最核心、最重要的那个数据,这个数据的地位可以类比成数据库中的主键那样,可以唯一确定一条数据。比如,我们需要传递的应该是用户id而不是用户的全部信息,用户的全部信息应该放在一种全局存储中。
比如我们现在需要跳转到用户个人资料界面,很多人可能直接传递下面这种参数:
// Don't do this
navigation.navigate('Profile', {
user: {
id: 'jane',
firstName: 'Jane',
lastName: 'Done',
age: 25,
},
});
但事实上,并不推荐这么做,这可能导致在界面上显示的是过时的数据,正确的做法应该是只传入用户的编号,而具体数据通过后续查询来得到:
navigation.navigate('Profile', { userId: 'jane' });
- navigate和push接受一个可选的第二个参数,让你向你正在导航的路由传递参数。例如navigation.navigate(‘RouteName’, { paramName: ‘value’ }) 。
- 你可以在一个屏幕内通过route.params读取参数
- 你可以通过 navigation.setParams 来更新屏幕的参数
- 初始参数可以通过屏幕上的initialParams来进行传递。
- 参数应该包含显示屏幕所需的最小数据,而不是更多