React-Native入坑第一天: 使用React-Navigator配置APP页面导航
前置: 为什么记录这篇文章,主要原因是我在配置React-Navagator导航的时候发现现在网上的很多的关于React-Navigator的配置教程都比较老了,和现在最新的React-Navigator不相对应,于是才转身到官网,跟着官网进行配置,并对这次使用React-Navigator的经历做一次记录:
- 在老版本的React-Navigator中对于APP页面路由的配置一般从react-navigation库中导入StackNavigation进行注册路由跳转,而路由跳转的一些配置则写在一个对象中作为参数传递给这个StackNavigator对象,有点类似Vue-router中的以对象配置路由的形式,如下:
安装react-navigation:yarn add react-navigation
import React from "react"
import {StackNavigator} from "react-navigation";
// 引入两个页面:
import Login from "./Login"
import Home from "./Home";
import Detail from "./Detail";
// 配置:
const App = StackNavigator({
// 这里配置项的screen就是类似Vue-router中的component选项,代表一个页面
Login: { screen: Login }, // 配置登录页
Home: { screen: Home },
Detail: {
screen: Detail,
// 跳转到某个页面的配置项
navigationOptions: ({navigation}) => {
id: '0001'
}
}
})
- 当然这里只是做了一个极简的配置项,但是在新版的react-Navigator中的页面路由配置就更加贴近于react-router的路由配置格式了:
安装依赖:
yarn add @react-navigation/native
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
yarn add @react-navigation/stack
创建一个最简单的页面跳转实现
// 引入依赖:
import * as React from "react"
import {View, Text} from "react-native"
// 导出创建路由导航的容器
import { NavigationContainer } from "@react-navigation/native"
// 创建路由
import { createStackNavigation } from "@react-navigation/stack"
// 引入两个页面
import Home from "./Home"
import Setting from "./Setting"
const stack = createStackNavigation()
function App() {
// 这里的创建其实和react-router-dom是十分类似的
return (
<NavigationContainer>
<Stack.Navigator>
// 这里的name属性就是之后跳转页面要用到的,并且当没有额外设置时这个Name属性将会作为这个页面的Header显示
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Setting" component={Setting} />
</Stack.Navigator>
</NavigationContainer>
)
}
export default App
- 如此处理之后再每个React Component中的props属性中都可以得到一个navigation对象,这个对象上封装了一些方法可以帮助完成页面的跳转以及页面间的params的传值, 这里简单举例一下:
import React from "react";
import { Text, Button,View } from "react-native";
function Home ({ navigation }) {
return (<>
<View>
<Text>This is Home page!</Text>
</View>
<Button
title="Go To Setting"
onPress={() => navigation.navigate("Setting", {
// 这个值将会作为params参数传递到Setting页面
itemId: Math.floor(Math.random() * 10000)
})}
/>
<Button
title="Go Back Page."
// goBack()API可以返回上一页
onPress={() => navigation.goBack()}
/>
</>)
}
export default Home
- 当然这里只是简单的两个API,也是比较常用的吧,更多的API大家可以去从官网查看: https://reactnavigation.org/docs/navigation-prop
多个页面中每个页面的header内容以及Header的样式设置
- 每个页面的顶部Header显示的文本内容或者是其他的一些内容是可以进行设置的,可以再Navigator上进行设置或者是Screen上进行设置:
// ... 前面的内容省略,和第一个一样
function App(){
return (<NavigationContainer>
<Stack.Navigator
screenOptions={{
//设置整体的header样式,所有页面共享,这里设置样式和在每个页面单独设置header样式内容基本是一样的,但还是有些只能够再各个单独的Screen上设置
headerStyle: {
// 这里设置的是整体的Header的容器样式
backgroundColor: "#f97d1c"
},
// 设置Header文字的颜色
headerTintColor: "#fff",
// 设置header的文字居中
headerTitleAlign: true
}}>
<Stack.Screen
name="Home"
component={Home}
options={{
title: "My Home",
// 在每个Screen上单独设置样式
headerStyle: {
// 设置header部分整体样式
backgroundColor: "#f97d1c",
},
// 设置header字体色
headerTintColor: "#fff",
// 设置Header居中
headerTitleAlign: true
}}
/>
<Stack.Screen
name="Setting"
component={Setting}
// options属性中设置的title属性是Header显示的文本内容
// 它可以是一个对象对title进行直接设置,同时也可以是一个函数,函数可以获取到一个route对象,这个对象和在每个React Component中可以接收到的那个route属性一样,可以获取到当前页面的一个params参数值
options={({route}) => ({title: `这是动态的Header: ${route.params.itemId}`})}
// 这里可以对Header进行自行设置,传一个组件给headerTitle即可
// headerTitle: props => <Header {...props} />,
// headerRight和HederLeft类似,可以为header中加入一些内容,比如这里加入一个 Button,它们分别在Header的右边和左边显示这个内容
// headerRight: () => (<Button
// title="this is Header Button"
// onPress={() => {alert("this is a Button")}}
// color="#666"
//>),
// 配置这个选项将会不显示header,从而达到一个全屏的效果
// headerShown: false
/>
</Stack.Navigator>
</NavigationContainer>)
}
- 这里也只是举了一些常使用的例子来对Header的内容进行配置,除此之外, 在navigation中还提供给了我们一个API: setOptions可以对当前这个页面的一些options选项进行动态设置:
<Button
title="Update Header"
onPress={() => {navigation.setOptions({title: "This is Update Header!"})}}
/>
配置页面Tabs
- 常见的App页面都是在其顶部或者在其底部有一个导航的页面Tabs(这里以底部的tabs为例,在react-navigation中配置一个底部的Tabs
装包: yarn add @react-navigation/bottom-tabs
引入: import {createBottomTabNavigator} from “@react-navigation/bottom-tabs”
// 部分前面相同的代码都省略,这里仍然是在App.js文件中进行的操作
import {createBottomTabNavigator} from "@react-navigation/bottom-tabs"
const const Tab = createBottomTabNavigator();
function App() {
return (<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</NavigationContainer>)
}
export default App
- 如此便会生成两个最简单的底部Tab选项
在Tabs上使用ICON图标
- 一般的页面的Tabs上都会有一个ICON图标进行显示,所以这里介绍一下如何在我们创建的Tabs上加入图标:
装包: yarn add react-native-vector-icons
引入: import Ionicons from “react-native-vector-icons/Ionicons”
import Ionicons from "react-native-vector-icons/Ionicons"
// 设置Icon图标:
<Tab.Navigator
screenOptions={({route}) => ({
// 设置Icons图标主要是根据图标的名字进行设置,而Ionicons的图标名字大家可以到网上去找找,也可以到 /node_modules/react-native-vector-icons/glyphmaps/Ionicons.json文件中去查看
tabBarIcon: ({focused, color, size}) => {
let iconName;
if(route.name === "Home") {
// 这里为了方便就都设置成一样的
iconName = focused ? 'home-circle' : 'home-circle'
}else if(route.name === "Setting") {
iconName = focused ? 'home-circle' : 'home-circle'
}
return <Ionicons name={iconName} size={size} color={color} />
}
})}
tabBarOptions={{
activeTintColor: 'tomato',
inactiveTintColor: 'gray',
}}
>
<Tab.Screen name="Home" component={Home}/>
<Tab.Screen name="Setting" component={Setting}/>
</Tab.Navigator>
- 这里使用到的是这个库里面的图标,当让我们也可以使用自定义的图标,比如iconfont上的图标,此时需要将iconfont上的图标下载下来,取出文件中的 .ttf文件,将该文件放到/node_modules/react-native-vector-icons/Fonts目录下,然后仿照Ionicons.js文件的格式创建一个iconfont.js文件:
import {createIconSet} from "react-native-vector-icons";
// 这里设置的就是iconfont中的图标,其键值就是在创建icon图标的时候使用的名字,而值大家可以去iconfont上去找到其unicode中的16进制数然后将其转化为十进制数即可
const glyphMap = {
"home-circle": 61697
}
const MyIcons = createIconSet(glyphMap, "iconfont", "iconfont.ttf")
export default MyIcons
创建右侧Drawer抽屉
- Drawer就是从左侧滑出的显示菜单的部分,在React-Navigation中也是可以创建的:
装包: yarn add @react-navigation/drawer
导入: import { createDrawerNavigator } from ‘@react-navigation/drawer’;
import { createDrawerNavigator } from '@react-navigation/drawer';
// 使用Drawer和创建Tabs是十分类似的:
const Drawer = createDrawerNavigator();
function App() {
return (<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={PageOne} />
<Drawer.Screen name="two" component={PageTwo} />
</Drawer.Navigator>
</NavigationContainer>)
}
export default App
- 这里便创建了一个简单的抽屉菜单(Drawer),当然在navigation对象中也提供了很多关于Drawer的API给我们使用,比如比较常用的打开和关闭Drawer的API: openDrawr和closeDrawer
// 其他部分省略
<Button
title="Toggle Drawer"
onPress={() => {
!this.state.showDrawer ? navigation.openDrawer() : navigation.closeDrawer();
this.setState(() => ({
showDrawer: !this.state.showDrawer
}))
}}
/>
对于React-Native中的导航配置就写这么多,可能是版本更新的原因,导致之前老版本的配置方法不太适用了,而网上很多的博客文章都是针对了老版本的react-navigation,所以专门去看了官网,将新版的配置进行简单的总结,希望对有望入坑RN的小伙伴们有帮助吧