这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战
基本使用
搭建项目
$ npx react-native init musicqq --template react-native-template-typescript
安装
$ npm install @react-navigation/native
or
$ yarn add @react-navigation/native
上面命令执行成功后,就安装了navigation的核心组件库了,但是在使用导航过程会涉及一些手势响应、动画交互、原生兼容等等;所以接下来安装一些支持这些操作的第三方依赖。
$ npm i react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
or
$ yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
React Native版本在0.6以上就不用手动
link
,React Native会自动link
。但是iOS端还是需要手动安装;进入ios文件夹,然后运行命令:pod install
(前提是已经安装了cocoapods环境)
在web浏览器中,您可以使用锚(<a>
)标记链接到不同的页面。当用户单击链接时,URL会被推送到浏览器历史堆栈中。当用户按下后退按钮时,浏览器将从历史堆栈顶部弹出该项,因此活动页面现在就是以前访问过的页面。React Native不像web浏览器那样有一个内置的api;React Navigation的堆栈导航器就提供了一种方式来在也,看之间转换和管理导航历史。如果你的应用程序只使用一个堆栈导航器,那么它在概念上类似于web浏览器处理导航状态的方式——当用户与应用程序交互时,你的应用程序从导航堆栈中推入和弹出项目,这导致用户看到不同的视图内容。这在网页浏览器和React Navigation中工作的一个关键区别是,React Navigation的堆栈导航器提供了手势和动画,你可以在Android和iOS上导航堆栈中的路由;安装堆栈式导航组件 @react-navigation/stack
$ yarn add @react-navigation/stack
实现Tab界面切换、界面间导航
API定义:StackNavigator(RouteConfigs, StackNavigatorConfig)、TabNavigator(RouteConfigs, TabNavigatorConfig)
-
安装依赖:
$ yarn add @react-navigation/bottom-tabs
-
创建Tab
// tab按钮的参数列表 export type BottomTabParamList = { Home: undefined; List: undefined; Found: undefined; Me: undefined; }; // Tab中包含 Navigator 和 Screen const Tab = createBottomTabNavigator<BottomTabParamList>();
-
引入组件,编写路由配置
// ....
import Home from '../pages/home/Home';
import List from '../pages/list/List';
import Found from '../pages/found/Found';
import Me from '../pages/me/Me';
// ...
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#f86442', // 修改tabbar激活颜色
}}>
<Tab.Screen
name="Home"
component={Home}
options={{ tabBarLabel: '首页' }}
/>
<Tab.Screen
name="List"
component={List}
options={{ tabBarLabel: '榜单' }}
/>
<Tab.Screen
name="Found"
component={Found}
options={{ tabBarLabel: '发现' }}
/>
<Tab.Screen
name="Me"
component={Me}
options={{ tabBarLabel: '我的' }}
/>
</Tab.Navigator>
// ...
正常情况下,页面底部就会出现四个tab按钮了,可以切换到对应的页面;但是切换后发现顶部的title都是“首页”,没有改变,接下来就实现顶部的title切换;
// route的类型
type Route = RouteProp<RootStackParamList, 'BottomTabs'> & {
state?: TabNavigationState<BottomTabParamList>;
};
// 定义组件的属性类型
interface IProps {
navigation: RootStackNavigation;
route: Route;
}
// 获取每个页面的标题
getHeaderTitle(route: Route): string {
// 传入当前页面的路由,获取路由的名称;如果没有就默认 Home
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
switch (routeName) {
case 'Home':
return '首页';
case 'List':
return '榜单';
case 'Found':
return '发现';
case 'Me':
return '我的';
default:
return '首页';
}
}
componentDidUpdate() {
const { navigation, route } = this.props;
navigation.setOptions({
headerTitle: this.getHeaderTitle(route),
});
}
这样就完整的实现了头部title切换,完整代码如下:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import React, { Component } from 'react';
import {
getFocusedRouteNameFromRoute,
RouteProp,
TabNavigationState,
} from '@react-navigation/native';
import { RootStackNavigation, RootStackParamList } from './index';
import Home from '../pages/home/Home';
import List from '../pages/list/List';
import Found from '../pages/found/Found';
import Me from '../pages/me/Me';
export type BottomTabParamList = {
Home: undefined;
List: undefined;
Found: undefined;
Me: undefined;
};
const Tab = createBottomTabNavigator<BottomTabParamList>();
type Route = RouteProp<RootStackParamList, 'BottomTabs'> & {
state?: TabNavigationState<BottomTabParamList>;
};
interface IProps {
navigation: RootStackNavigation;
route: Route;
}
export default class BottomTabs extends Component<IProps> {
// 获取每个页面的标题
getHeaderTitle(route: Route): string {
const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';
switch (routeName) {
case 'Home':
return '首页';
case 'List':
return '榜单';
case 'Found':
return '发现';
case 'Me':
return '我的';
default:
return '首页';
}
}
componentDidUpdate() {
const { navigation, route } = this.props;
navigation.setOptions({
headerTitle: this.getHeaderTitle(route),
});
}
render() {
return (
<Tab.Navigator
tabBarOptions={{
activeTintColor: '#f86442', // 修改tabbar激活颜色
}}>
<Tab.Screen
name="Home"
component={Home}
options={{ tabBarLabel: '首页' }}
/>
<Tab.Screen
name="List"
component={List}
options={{ tabBarLabel: '榜单' }}
/>
<Tab.Screen
name="Found"
component={Found}
options={{ tabBarLabel: '发现' }}
/>
<Tab.Screen
name="Me"
component={Me}
options={{ tabBarLabel: '我的' }}
/>
</Tab.Navigator>);
}
}
StackNavigator还提供了onNavigationStateChange回调方法,用来监听导航状态的改变。实现了界面跳转和切换,那么就该来增加下界面之间的感情了,来看看如何实现界面之间的传值和取值。
界面间跳转、传值、取值
在界面组件注入到StackNavigator
中时,界面组件就被赋予了navigation
属性,即在界面组件中可以通过this.props.navigation
获取并进行一些操作。
navigation
属性中提供了很多的函数简化界面间操作,简单列举几点:
-
通过navigate函数实现界面之间跳转:
const { navigation } = this.props; navigation.navigate('Detail'); // 跳转到详情页
参数为我们在StackNavigator注册界面组件时的名称。同样也可以从当前页面返回到上一页:
const { navigation } = this.props; navigation.goBack(); // 返回上一页
-
跳转时传值:
const { navigation } = this.props; navigation.navigate('Detail', { topId: 'see3x5dfw6' }); // 路由传参
第一个参数同样为要跳转的界面组件名称,第二个参数为要传递的参数,topid可以理解为key,后面即传递的参数。
-
获取路由参数:
const { topId } = this.props.route.params; // 获取topId
通过route.params来获取传来的参数,后面为key值。此处为topId。