[TOC]
导入react-navigation
- 安装基础库
npm install @react-navigation/native
- 安装依赖库
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
- iOS项目安装依赖库
npx pod-install ios
- 引用库,在 index.js 和 app.js 等入口文件中
import 'react-native-gesture-handler';
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
export default function App() {
return (
<NavigationContainer>{/* Rest of your app code */}</NavigationContainer>
);
}
- 安装导航栏管理栈
npm install @react-navigation/stack
- 例子:在项目中引用库
// In App.js in a new project
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
function HomeScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
const Stack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
到这里,基本上已经配置好导航栏的环境,最后一个例子也提供了如何使用这个库。后面会讲解这个库的常用API的使用方式。
使用react-navigation
定义一个导航栏的视图
定义一个导航栏控制栈
const Stack = createStackNavigator();
1、栈里只有一个视图
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
2、栈里有多个视图
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
3、其他定义格式
function App() {
return (
<NavigationContainer>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Overview' }}
/>
</NavigationContainer>
);
}
推出一个新的视图
按照上面的第二种方式定义导航栏
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
1、navigation.navigate('Details')
:以一个新的导航栏控制栈推出视图
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
<Button
title="Go to Details"
onPress={() => navigation.navigate('Details')}
/>
</View>
);
}
2、navigation.push('Details')
:从当前栈推出一个新的视图
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')}
/>
</View>
);
}
3、两者区别
navigation.navigate('Details')
- 会创建一个新的
Stack
- 如果当前视图是
Details
,则不能在当前视图 navigation.navigate('Details') 推出一个新的Details
界面
navigation.push('Details')
- 不会创建一个新的
Stack
,仍然在当前栈的基础上推出新的视图 - 如果当前视图是
Details
,也可以使用navigation.push('Details')
推出一个新的Details
界面
返回上一个界面
1、返回指定界面:navigation.navigate("Home")
- 如果
Home
已经存在,则会返回到Home
界面,可以用这种方式返回到指定的界面 - 如果
Home
不存在,则会创建一个新的Stack
并推出一个新的视图
<Button title="Go to Home" onPress={() => navigation.navigate("Home")} />
2、返回上一个界面:navigation.goBack()
<Button title="Go back" onPress={() => navigation.goBack()} />
3、返回第一个界面:navigation.popToTop()
<Button title="Go back to first screen in stack" onPress={() => navigation.popToTop()} />
导航栏的参数传递
正向传递
- 页面打开顺序:
A -> B
- 参数传递顺序:
A -> B
- 参数传递方式:
navigation.navigate(obj)
、navigation.push(obj)
1、navigation.navigate(obj)
使用示例
navigation.navigate('Details', {
itemId: 886,
otherParam: '传递任何你想传递的',
})
2、navigation.push(obj)
使用示例
navigation.push('Details', {
itemId: Math.floor(Math.random() * 100),
})
从上面两个例子可以看出来,他们的传递方式其实是一模一样的:
- 第一个参数:表示要跳转的页面
- 第二个参数:表示要传递的对象
3、获取参数传递内容
参数传过来了,只有准确拿到传过来的参数并且被解析了才是我们想要的结果
-
获取传递对象:
function DetailsScreen({ route, navigation }) {...}
,通过route
,我们可以拿到传递过来的对象 -
解析传递对象:
const { itemId , otherParam} = route.params;
,我们在传递的时候定义的对象的key值就是itemId
和otherParam
-
使用解析结果:虽然上一步对传递的 route 对象进行了解析,但我们并不能直接使用这个结果,官方解释说它是一个json格式的数据,需要解析才可以使用
We recommend that the params you pass are JSON-serializable. That way, you'll be able to use state persistence and your screen components will have the right contract for implementing deep linking.
使用
JSON.stringify(itemId)
对结果进行解析,将json数据转成字符串,具体使用方式如下:<Text>itemId: {JSON.stringify(itemId)}</Text> <Text>otherParam: {JSON.stringify(otherParam)}</Text>
反向传递
- 页面打开顺序:
A -> B
- 参数传递顺序:
B -> A
- 参数传递方式:
navigation.navigate(obj)
结合 返回上一个界面
这节里面的内容,其实我们可以推断出反向传递的实现过程。
-
返回上一个界面
有两种方法 ——navigation.goBack()
和navigation.navigate("Home")
,其中navigation.navigate("Home")
方法也可以作为推出新的页面的方法 - 同理可得,
navigation.navigate(obj)
可以用作正向参数传递,因为它可以返回上一个(指定)界面,所以它也可以用做反向传值。学习就是举一反三的过程,下面来看个反向传值的例子
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 params back to home screen
navigation.navigate('Home', { post: postText });
}}
/>
</>
);
}
更新参数 & 初始化参数
1、初始化参数 initialParams
如果没有传特定的值,那么就会使用初始化参数里面的数值。例如下面例子中的 itemId: 42
,如果obj的参数传递中并没有指定 itemId
,那么就会使用这个初始值 42
<Stack.Screen
name="Details"
component={DetailsScreen}
initialParams={{ itemId: 42 }}
/>
2、更新参数 setParams
这个方法可以可以更新 route.params
中的参数,类似于组件中的 setState
方法,主要用于刷新当前页面中 setState。使用例子如下:
function ProfileScreen({ navigation: { setParams } }) {
render() {
return (
<Button
onPress={() =>
setParams({
friends:
route.params.friends[0] === 'Brent'
? ['Wojciech', 'Szymon', 'Jakub']
: ['Brent', 'Satya', 'Michaś'],
title:
route.params.title === "Brent's Profile"
? "Lucy's Profile"
: "Brent's Profile",
})
}
title="Swap title and friends"
/>
);
}
}
网友评论