安装辅助包
npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack
cd ./FirstApp/ios && pod install
cd FirstAppnpx react-native start
cd FirstAppnpx react-native run-ios
// In App.js in a new projectimport * as React from 'react';import { View, Text } from 'react-native';import { NavigationContainer } from '@react-navigation/native';import { createNativeStackNavigator } from '@react-navigation/native-stack';function HomeScreen() {return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Home Screen</Text></View>);}const Stack = createNativeStackNavigator();function App() {return (<NavigationContainer><Stack.Navigator><Stack.Screen name="Home" component={HomeScreen} /></Stack.Navigator></NavigationContainer>);}export default App;
基本概念方法的总结
Hello React Navigation
- React Native doesn’t have a built-in API for navigation like a web browser does. React Navigation provides this for you, along with the iOS and Android gestures and animations to transition between screens.
- Stack.Navigator is a component that takes route configuration as its children with additional props for configuration and renders our content.
- Each Stack.Screen component takes a name prop which refers to the name of the route and component prop which specifies the component to render for the route. These are the 2 required props.
- To specify what the initial route in a stack is, provide an initialRouteName as the prop for the navigator.
To specify screen-specific options, we can pass an options prop to Stack.Screen, and for common options, we can pass screenOptions to Stack.Navigator
React Native不像网页浏览器那样内置导航API。React Navigation为您提供了这一点,以及iOS和Android手势和动画,以便在屏幕之间过渡。
- Stack.Navigator是一个以路由配置为子组件,具有额外的配置道具并呈现我们的内容。
- 每个Stack.Screen组件都使用一个name道具,该名称道具指的是路由的名称和component道具,该道具指定要为路由渲染的组件。这些是2个必需的道具。
- 要指定堆栈中的初始路由是什么,请提供initialRouteName作为导航器的道具。
要指定特定于屏幕的选项,我们可以将options道具传递给Stack.Screen,对于常见选项,我们可以将screenOptions传递给Stack.Navigator
Moving between screens
navigation.navigate(‘RouteName’) pushes a new route to the native stack navigator if it’s not already in the stack, otherwise it jumps to that screen.
- We can call navigation.push(‘RouteName’) as many times as we like and it will continue pushing routes.
- The header bar will automatically show a back button, but you can programmatically go back by calling navigation.goBack(). On Android, the hardware back button just works as expected.
- You can go back to an existing screen in the stack with navigation.navigate(‘RouteName’), and you can go back to the first screen in the stack with navigation.popToTop().
The navigation prop is available to all screen components (components defined as screens in route configuration and rendered by React Navigation as a route).
navigation.navigate(‘RouteName’)如果新路由尚未在堆栈中,则将其推送到本机堆栈导航器,否则它会跳转到该屏幕。
- 我们可以根据需要多次调用 navigation.push(‘RouteName’),它将继续推送路线。
- 标题栏将自动显示一个后退按钮,但您可以通过调用navigation.goBack()以编程方式返回。在Android上,硬件后退按钮工作正常。
- You can go back to an existing screen in the stack with navigation.navigate(‘RouteName’), and you can go back to the first screen in the stack with navigation.popToTop().
- navigation道具适用于所有屏幕组件(在路由配置中定义为屏幕并由React Navigation渲染为路由的组件)。
Passing parameters to routes
navigateandpushaccept an optional second argument to let you pass parameters to the route you are navigating to. For example:navigation.navigate('RouteName', { paramName: 'value' }).- You can read the params through
route.paramsinside a screen - You can update the screen’s params with
navigation.setParams - Initial params can be passed via the
initialParamsprop on Screen Params should contain the minimal data required to show a screen, nothing more
navigate并push接受可选的第二个参数,以便您将参数传递到导航到的路线。例如: navigation.navigate(‘RouteName’, { paramName: ‘value’ })
- You can read the params through route.params inside a screen
- 您可以使用navigation.setParams
- 初始参数可以通过initialParams道具传递Screen
- 参数应该包含显示屏幕所需的最小数据,仅此而已
如果您有嵌套导航器,您需要以不同的方式传递参数。例如,假设您在Account屏幕内有一个导航器,并希望将参数传递到该导航器内的Settings屏幕。然后,您可以通过以下参数传递:
navigation.navigate('Account', {screen: 'Settings',params: { user: 'jane' },});
Configuring the header bar
- You can customize the header inside of the
optionsprop of your screen components. Read the full list of options in the API reference. - The
optionsprop can be an object or a function. When it is a function, it is provided with an object with thenavigationandrouteprop. You can also specify shared
screenOptionsin the stack navigator configuration when you initialize it. The prop takes precedence over that configuration.您可以自定义屏幕组件options道具内的标题。阅读API参考中的完整选项列表。
- options道具可以是对象或函数。当它是一个函数时,它会被提供一个带有当时navigation和route道具的对象。
- 您还可以在初始化堆栈导航器配置时指定共享screenOptions。道具优先于该配置。
可以在createNativeStackNavigator引用中阅读本机堆栈导航器内部屏幕可用options的完整列表。
Header buttons
- You can set buttons in the header through the
headerLeftandheaderRightproperties inoptions. - The back button is fully customizable with
headerLeft, but if you just want to change the title or image, there are otheroptionsfor that —headerBackTitle,headerBackTitleStyle, andheaderBackImageSource. You can use a callback for the options prop to access
navigationandrouteobjects.您可以通过options中的headerLeft和headerRight属性在标题中设置按钮。
- 返回按钮可以使用headerLeft完全自定义,但如果您只想更改标题或图像,还有其他options——headerBackTitle、headerBackTitleStyle和headerBackImageSource。
- 您可以使用选项道具的回调来访问navigation和route对象。
综合修改后的源码
// In App.js in a new projectimport * as React from 'react';import { View, Text, Button, TextInput, Image, Alert } from 'react-native';import { NavigationContainer } from '@react-navigation/native';import { createNativeStackNavigator } from '@react-navigation/native-stack';const HomeScreen = ({ navigation, route }: any) => {const [count, setCount] = React.useState(0);React.useLayoutEffect(() => {navigation.setOptions({headerRight: () => (<Button onPress={() => setCount(c => c + 1)} title="Update count" />),});}, [navigation]);return (<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}><Text>Home Screen</Text><Text>Count: {count}</Text><Buttontitle="Go to Details"onPress={() => navigation.navigate('Details')}/*,{itemId: 86,otherParam: 'anything you want here',})}*//><Buttontitle="Create post"onPress={() => navigation.navigate('CreatePost')}/><Text style={{ margin: 10 }}>Post: {route.params?.post}</Text></View>);}const DetailsScreen = ({navigation, route}: any) => {const { itemId, otherParam } = route.params;navigation.setOptions({title: "Detail " + itemId})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><Buttontitle="Call setParams to change itemId"onPress={() => navigation.setParams({itemId: Math.floor(Math.random() * 100)})}/><Buttontitle="Navigate to Details... again"onPress={() => navigation.navigate('Details')}/><Buttontitle="Push 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()} /><Buttontitle="Go back to first screen in stack"onPress={() => navigation.popToTop()}/></View>);}const CreatePostScreen = ({ navigation}: any ) => {const [postText, setPostText] = React.useState('');return (<><TextInputmultilineplaceholder="What's on your mind?"style={{ height: 200, padding: 10, backgroundColor: 'white' }}value={postText}onChangeText={setPostText}/><Buttontitle="Done"onPress={() => {navigation.navigate({name: 'Home',params: { post: postText },merge: true,});}}/></>)}const defaultStyle = {headerStyle: {backgroundColor: '#f4511e',},headerTintColor: '#fff',headerTitleStyle: {fontWeight: 'bold',},}const screenOptions = {title: 'Overview',headerTintColor: '#000',headerTitle: (props: any) => <LogoTitle {...props} /> ,/*headerRight: () => (<ButtononPress={() => Alert.alert('This is a button!')}title="Info"color="#fff"/>),*/}const LogoTitle = () => {return (<Imagestyle={{ width: 25, height: 25 }}source={require('react-native/Libraries/NewAppScreen/components/logo.png')}/>);}const detailScreenInitialParams = {itemId: 88}const PageStack = createNativeStackNavigator();const App = () => {return (<NavigationContainer><PageStack.Navigator initialRouteName="Home" screenOptions={defaultStyle}><PageStack.Screen name="Home" component={HomeScreen} options={screenOptions} /><PageStack.Screen name="Details" component={DetailsScreen} initialParams={detailScreenInitialParams}/><PageStack.Screen name="CreatePost" component={CreatePostScreen} options={{title: "Create Post"}}/></PageStack.Navigator></NavigationContainer>);}export default App;
嵌套导航器
https://reactnavigation.org/docs/nesting-navigators
导航生命周期
https://reactnavigation.org/docs/navigation-lifecycle
小结
现在你应该熟悉了如何创建本机堆栈导航器,在屏幕组件上配置它,在路由之间导航,以及显示全屏模式。本机堆栈导航器及其相关API将是React导航工具带中最常用的工具,但有些问题无法解决。例如,您无法使用堆栈导航器构建基于选项卡的导航——为此,你需要使用TabNavigator。
