目录一、创建项目二、组件介绍2.1、Text、View和Image组件2.2、文件式导航(Link)2.3、堆栈导航(Stack)2.4、浅色与深色主题2.5、主题化UI组件2.6、路由分组与嵌套布局2.7、Pressable组件2.8、标签栏导航(Tabs)2.9、安全区域适配(SafeAreaView)一、创建项目Expo官网Expo Documentation 中文官网教程介绍 - Expo 中文网创建一个文件夹在VS Code的终端下输入命令npx create-expo-applatest --template blank ./创建出一个空白模板的app在英文官网首页点击Set up your environment - Expo Documentation设置路由Install Expo Router - Expo Documentation二、组件介绍2.1、Text、View和Image组件效果展示import { StyleSheet, Text, View, Image } from react-native; import Logo from ../assets/system.png; export default function Page() { return ( View style{styles.container} {/* 文本 */} Text style{styles.title}The Number 1/Text {/* 内联样式 */} Text style{{ marginTop: 10 }}Welcome to Expo/Text {/* 外部样式内联样式 */} Text style{[styles.title,{color:gold}]}Reading this app/Text {/* 图片 */} Image style{styles.img} source{Logo} / /View ); } const styles StyleSheet.create({ container: { flex: 1, backgroundColor: skyblue, alignItems: center, justifyContent: center, }, title: { fontSize: 20, fontWeight: bold, }, img: { borderRadius: 50%, marginVertical: 10, }, });2.2、文件式导航(Link)import { Link } from expo-router; {/* 跳转 相当于HTML中的a标签 */} Link href/about跳转到about页面/Link2.3、堆栈导航(Stack)为了产生页面的返回键和页面标题前提在app文件夹下建立_layout.jsx文件。import { Stack } from expo-router; const RootLayout () { return ( Stack screenOptions{{ headerStyle: { backgroundColor: #ddd }, headerTintColor: #333, }} Stack.Screen nameindex options{{title: Home}}/ Stack.Screen nameabout options{{title: About}}/ Stack.Screen namecontact options{{title: Contact}}/ /Stack ); }; export default RootLayout; // 如果第一步安装路由启动失败加上_layout.jsx这个文件 // 可以重新安装依赖rm -rf node_modules package-lock.json npm install // 想在web端查看页面npx expo install react-dom react-native-web // 再重新运行npx expo start2.4、浅色与深色主题import { useColorScheme } from react-native; import { Colors } from ../constants/Color; import { StatusBar } from expo-status-bar; const RootLayout () { const colorScheme useColorScheme(); const theme Colors[colorScheme] ?? Colors.light; return ( StatusBar valueauto / / ); };2.5、主题化UI组件以View为例import { View, useColorScheme } from react-native; import {Colors} from ../constants/Color; const ThemeView ({ style, children, ...props }) { const colorScheme useColorScheme(); const theme Colors[colorScheme] ?? Colors.light; return ( View style{[style, { backgroundColor: theme.background }]} {...props} {children} /View ); }; export default ThemeView;其实可以自己选组件库React Native Elements、React Native Paper和UI Kitten的文档如下(兼容IOS和安卓后面两个可以搭配使用)Overview | React Native ElementsActivityIndicator | React Native PaperUI Kitten - React Native Components2.6、路由分组与嵌套布局路由分组将功能相关的路由归类统一管理配置如认证路由和主应用路由分离在app文件夹下再建一个文件夹命名时用()括起来此时页面title会变为(auth/login),此时想要取消页面的Header显示则需要在(auth)文件夹下再建立一个_layout.jsximport { Stack } from expo-router; import { StatusBar } from expo-status-bar; const AuthLayout () { return ( StatusBar valueauto / Stack screenOptions{{ headerShown: false, animation: none, }} /Stack / ); }; export default AuthLayout;在RootLayout.jsx里Stack.Screen name(auth) options{{headerShown: false}}/或者使用createNativeStackNavigator分组// App.js import { createNativeStackNavigator } from react-navigation/native-stack; const AuthStack createNativeStackNavigator(); const MainStack createNativeStackNavigator(); function AuthGroup() { return ( AuthStack.Navigator AuthStack.Screen nameLogin component{LoginScreen} / AuthStack.Screen nameRegister component{RegisterScreen} / /AuthStack.Navigator ); } function MainGroup() { return ( MainStack.Navigator MainStack.Screen nameHome component{HomeScreen} / MainStack.Screen nameProfile component{ProfileScreen} / /MainStack.Navigator ); } // 根导航器整合分组 const RootStack createNativeStackNavigator(); function App() { return ( NavigationContainer RootStack.Navigator RootStack.Screen nameAuth component{AuthGroup} options{{ headerShown: false }} / RootStack.Screen nameMain component{MainGroup} options{{ headerShown: false }} / /RootStack.Navigator /NavigationContainer ); }拓展1. 路由参数传递// 父路由传递参数给子路由 Stack.Screen nameProfile component{ProfileScreen} initialParams{{ userId: 123 }} / // 子路由获取参数 function ProfileScreen({ route }) { const { userId } route.params; }2. 统一导航选项// 分组统一配置 Stack.Navigator screenOptions{{ headerStyle: { backgroundColor: #4CAF50 }, headerTintColor: white }} {/* 所有子路由继承此样式 */} /Stack.Navigator3、动态隐藏HeaderheaderShown: false2.7、Pressable组件用于检测各种按压交互点击、长按等自定义组件ThemeBtn.jsximport { StyleSheet, Pressable } from react-native; const ThemeBtn ({ style, ...props }) { return ( Pressable style{({ pressed }) [ styles.button, pressed styles.buttonPressed, style, ]} {...props} / ); }; export default ThemeBtn; const styles StyleSheet.create({ button: { padding: 18, marginVertical: 10, borderRadius: 6, backgroundColor: #6849a7, }, buttonPressed: { opacity: 0.5, }, });父组件引用import ThemeBtn from ../../components/ThemeBtn; const Login () { const handleSubmit () { console.log(submit); }; return ( View ThemeBtn onPress{handleSubmit} Text style{{ color: #f2f2f2, textAlign: center }}Press Me/Text /ThemeBtn /View ); }; export default Login;列表项按压效果function ListItem({ item }) { return ( Pressable onPress{() navigate(Detail, { id: item.id })} style{({ pressed }) ({ padding: 16, backgroundColor: pressed ? #f0f0f0 : white, })} Text{item.name}/Text /Pressable ); }2.8、标签栏导航(Tabs)建立(dashboard)文件夹分别建立三个.jsx文件profile、books、createimport { Tabs } from expo-router; import { useColorScheme } from react-native; import { Colors } from ../../constants/Color; // 下载图标 npm i expo/vector-icons , 默认自带 import { Ionicons } from expo/vector-icons; const DashboardLayout () { const colorScheme useColorScheme(); const theme colorScheme dark ? Colors.dark : Colors.light; return ( Tabs screenOptions{{ headerShown: false, tabBarStyle: { backgroundColor: theme.navBackground, paddingTop: theme.iconColor, height: 90, }, tabBarActiveTintColor: theme.iconColorFocused, tabBarInactiveTintColor: theme.iconColor, }} {/* 自定义底部导航栏标题和图标 */} Tabs.Screen nameprofile options{{ title: Profile, tabBarIcon: ({ focused }) ( Ionicons name{focused ? person : person-outline} size{24} color{focused ? theme.iconColorFocused : theme.iconColor} / ), }} / Tabs.Screen namebooks options{{ title: Books }} / Tabs.Screen namecreate options{{ title: Create }} / /Tabs ); }; export default DashboardLayout;2.9、安全区域适配(SafeAreaView)SafeAreaView直接包裹当前页面但是无法灵活控制具体哪一侧需要安全边距所以选择以下HOOkuseSafeAreaInsets()可以手动获取安全区域的 top、bottom、left、right 值并应用到样式中import { View, useColorScheme } from react-native; import { Colors } from ../constants/Color; import { useSafeAreaInsets } from react-native-safe-area-context; const ThemeView ({ style, safe false, ...props }) { const colorScheme useColorScheme(); const theme Colors[colorScheme] ?? Colors.light; if (!safe) return ( View style{[style, { backgroundColor: theme.background }]} {...props} / ); const insets useSafeAreaInsets(); return ( View style{[ style, { backgroundColor: theme.background, paddingTop: insets.top, // 避开刘海 paddingBottom: insets.bottom, // 避开底部横条 }, ]} {...props} / ); }; export default ThemeView;