Skip to Content
Nextra 4.0 is released 🎉
框架 & 库React Native

React Native 学习指南

React Native 是一个使用 React 和 JavaScript 构建原生移动应用的框架。它允许开发者使用相同的代码库为 iOS 和 Android 平台开发应用,同时保持原生性能。

🚀 快速开始

创建 React Native 项目

# 使用 React Native CLI npx react-native@latest init MyApp # 使用 Expo CLI (推荐新手) npx create-expo-app@latest MyApp # 使用 TypeScript 模板 npx react-native@latest init MyApp --template react-native-template-typescript

基本项目结构

MyApp/ ├── android/ # Android 原生代码 ├── ios/ # iOS 原生代码 ├── src/ # 源代码 │ ├── components/ # 组件 │ ├── screens/ # 页面 │ ├── navigation/ # 导航 │ ├── services/ # 服务 │ └── utils/ # 工具函数 ├── App.js # 应用入口 ├── package.json # 依赖配置 └── metro.config.js # Metro 配置

📚 核心概念

基础组件

// App.js import React from 'react'; import { SafeAreaView, ScrollView, StatusBar, StyleSheet, Text, View, } from 'react-native'; export default function App() { return ( <SafeAreaView style={styles.container}> <StatusBar barStyle="dark-content" /> <ScrollView contentInsetAdjustmentBehavior="automatic"> <View style={styles.section}> <Text style={styles.sectionTitle}>Welcome to React Native!</Text> <Text style={styles.sectionDescription}> Edit App.js to change this screen and then come back to see your edits. </Text> </View> </ScrollView> </SafeAreaView> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, section: { marginTop: 32, paddingHorizontal: 24, }, sectionTitle: { fontSize: 24, fontWeight: '600', color: '#000', }, sectionDescription: { marginTop: 8, fontSize: 18, fontWeight: '400', color: '#666', }, });

常用组件

import React, { useState } from 'react'; import { View, Text, TextInput, TouchableOpacity, Image, FlatList, Alert, } from 'react-native'; export default function BasicComponents() { const [text, setText] = useState(''); const [items, setItems] = useState(['Item 1', 'Item 2', 'Item 3']); const addItem = () => { if (text.trim()) { setItems([...items, text]); setText(''); } }; const showAlert = () => { Alert.alert('提示', '这是一个警告框', [ { text: '取消', style: 'cancel' }, { text: '确定', onPress: () => console.log('确定') }, ]); }; return ( <View style={{ flex: 1, padding: 20 }}> {/* 文本输入 */} <TextInput style={{ borderWidth: 1, borderColor: '#ccc', padding: 10, marginBottom: 10, }} placeholder="输入文本" value={text} onChangeText={setText} /> {/* 按钮 */} <TouchableOpacity style={{ backgroundColor: '#007AFF', padding: 15, borderRadius: 8, marginBottom: 10, }} onPress={addItem} > <Text style={{ color: 'white', textAlign: 'center' }}>添加项目</Text> </TouchableOpacity> {/* 图片 */} <Image source={{ uri: 'https://reactnative.dev/img/tiny_logo.png' }} style={{ width: 100, height: 100, marginBottom: 10 }} /> {/* 列表 */} <FlatList data={items} keyExtractor={(item, index) => index.toString()} renderItem={({ item }) => ( <Text style={{ padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee' }}> {item} </Text> )} /> {/* 警告框 */} <TouchableOpacity style={{ backgroundColor: '#FF3B30', padding: 15, borderRadius: 8, marginTop: 10, }} onPress={showAlert} > <Text style={{ color: 'white', textAlign: 'center' }}>显示警告</Text> </TouchableOpacity> </View> ); }

⚡ 样式和布局

Flexbox 布局

import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; export default function FlexboxExample() { return ( <View style={styles.container}> {/* 行布局 */} <View style={styles.row}> <View style={[styles.box, styles.red]} /> <View style={[styles.box, styles.green]} /> <View style={[styles.box, styles.blue]} /> </View> {/* 列布局 */} <View style={styles.column}> <View style={[styles.box, styles.red]} /> <View style={[styles.box, styles.green]} /> <View style={[styles.box, styles.blue]} /> </View> {/* 居中布局 */} <View style={styles.center}> <Text style={styles.text}>居中文本</Text> </View> {/* 绝对定位 */} <View style={styles.absolute}> <Text style={styles.text}>绝对定位</Text> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, row: { flexDirection: 'row', justifyContent: 'space-between', padding: 20, }, column: { flexDirection: 'column', alignItems: 'center', padding: 20, }, center: { flex: 1, justifyContent: 'center', alignItems: 'center', }, absolute: { position: 'absolute', top: 50, right: 20, backgroundColor: 'rgba(0,0,0,0.7)', padding: 10, borderRadius: 5, }, box: { width: 60, height: 60, borderRadius: 8, }, red: { backgroundColor: '#FF3B30', }, green: { backgroundColor: '#34C759', }, blue: { backgroundColor: '#007AFF', }, text: { color: 'white', fontSize: 16, fontWeight: 'bold', }, });

响应式设计

import React from 'react'; import { View, Text, StyleSheet, Dimensions } from 'react-native'; const { width, height } = Dimensions.get('window'); export default function ResponsiveDesign() { return ( <View style={styles.container}> <View style={styles.card}> <Text style={styles.title}>响应式卡片</Text> <Text style={styles.description}> 屏幕宽度: {width}px{'\n'} 屏幕高度: {height}px </Text> </View> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: width * 0.05, // 5% 的屏幕宽度 backgroundColor: '#f5f5f5', }, card: { backgroundColor: 'white', borderRadius: 12, padding: 20, shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, }, title: { fontSize: Math.max(16, width * 0.04), // 最小 16px,最大 4% 屏幕宽度 fontWeight: 'bold', marginBottom: 10, }, description: { fontSize: Math.max(14, width * 0.035), color: '#666', lineHeight: 20, }, });

🎯 导航系统

React Navigation

# 安装导航库 npm install @react-navigation/native @react-navigation/stack @react-navigation/bottom-tabs npm install react-native-screens react-native-safe-area-context
// App.js import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import HomeScreen from './src/screens/HomeScreen'; import ProfileScreen from './src/screens/ProfileScreen'; import SettingsScreen from './src/screens/SettingsScreen'; import DetailScreen from './src/screens/DetailScreen'; const Stack = createStackNavigator(); const Tab = createBottomTabNavigator(); function TabNavigator() { return ( <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} options={{ title: '首页', tabBarIcon: ({ color, size }) => ( <Text style={{ color, fontSize: size }}>🏠</Text> ), }} /> <Tab.Screen name="Profile" component={ProfileScreen} options={{ title: '个人', tabBarIcon: ({ color, size }) => ( <Text style={{ color, fontSize: size }}>👤</Text> ), }} /> <Tab.Screen name="Settings" component={SettingsScreen} options={{ title: '设置', tabBarIcon: ({ color, size }) => ( <Text style={{ color, fontSize: size }}>⚙️</Text> ), }} /> </Tab.Navigator> ); } export default function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Main" component={TabNavigator} options={{ headerShown: false }} /> <Stack.Screen name="Detail" component={DetailScreen} options={{ title: '详情' }} /> </Stack.Navigator> </NavigationContainer> ); }

页面组件

// src/screens/HomeScreen.js import React from 'react'; import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; export default function HomeScreen({ navigation }) { return ( <View style={styles.container}> <Text style={styles.title}>首页</Text> <TouchableOpacity style={styles.button} onPress={() => navigation.navigate('Detail', { id: 1 })} > <Text style={styles.buttonText}>跳转到详情</Text> </TouchableOpacity> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, }, button: { backgroundColor: '#007AFF', padding: 15, borderRadius: 8, }, buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold', }, });
// src/screens/DetailScreen.js import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; export default function DetailScreen({ route }) { const { id } = route.params; return ( <View style={styles.container}> <Text style={styles.title}>详情页面</Text> <Text style={styles.description}>ID: {id}</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 10, }, description: { fontSize: 16, color: '#666', }, });

🔧 状态管理

Context API

// src/contexts/AppContext.js import React, { createContext, useContext, useState } from 'react'; const AppContext = createContext(); export function AppProvider({ children }) { const [user, setUser] = useState(null); const [theme, setTheme] = useState('light'); const login = (userData) => { setUser(userData); }; const logout = () => { setUser(null); }; const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light'); }; return ( <AppContext.Provider value={{ user, theme, login, logout, toggleTheme, }}> {children} </AppContext.Provider> ); } export function useApp() { const context = useContext(AppContext); if (!context) { throw new Error('useApp must be used within AppProvider'); } return context; }

使用 Context

// src/screens/ProfileScreen.js import React from 'react'; import { View, Text, TouchableOpacity, StyleSheet } from 'react-native'; import { useApp } from '../contexts/AppContext'; export default function ProfileScreen() { const { user, theme, logout, toggleTheme } = useApp(); return ( <View style={[styles.container, { backgroundColor: theme === 'dark' ? '#000' : '#fff' }]}> <Text style={[styles.title, { color: theme === 'dark' ? '#fff' : '#000' }]}> 个人资料 </Text> {user ? ( <View> <Text style={[styles.text, { color: theme === 'dark' ? '#fff' : '#000' }]}> 用户名: {user.name} </Text> <Text style={[styles.text, { color: theme === 'dark' ? '#fff' : '#000' }]}> 邮箱: {user.email} </Text> <TouchableOpacity style={styles.button} onPress={logout}> <Text style={styles.buttonText}>退出登录</Text> </TouchableOpacity> </View> ) : ( <Text style={[styles.text, { color: theme === 'dark' ? '#fff' : '#000' }]}> 请先登录 </Text> )} <TouchableOpacity style={styles.themeButton} onPress={toggleTheme}> <Text style={styles.buttonText}> 切换主题 ({theme}) </Text> </TouchableOpacity> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, }, text: { fontSize: 16, marginBottom: 10, }, button: { backgroundColor: '#FF3B30', padding: 15, borderRadius: 8, marginTop: 20, }, themeButton: { backgroundColor: '#007AFF', padding: 15, borderRadius: 8, marginTop: 20, }, buttonText: { color: 'white', textAlign: 'center', fontSize: 16, fontWeight: 'bold', }, });

📦 网络请求

Fetch API

// src/services/api.js const BASE_URL = 'https://api.example.com'; export const api = { async get(endpoint) { try { const response = await fetch(`${BASE_URL}${endpoint}`); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { console.error('API Error:', error); throw error; } }, async post(endpoint, data) { try { const response = await fetch(`${BASE_URL}${endpoint}`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data), }); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return await response.json(); } catch (error) { console.error('API Error:', error); throw error; } }, };

使用 API

// src/screens/PostsScreen.js import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet, ActivityIndicator, } from 'react-native'; import { api } from '../services/api'; export default function PostsScreen({ navigation }) { const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetchPosts(); }, []); const fetchPosts = async () => { try { setLoading(true); const data = await api.get('/posts'); setPosts(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; const renderPost = ({ item }) => ( <TouchableOpacity style={styles.postItem} onPress={() => navigation.navigate('Detail', { post: item })} > <Text style={styles.postTitle}>{item.title}</Text> <Text style={styles.postExcerpt}>{item.body}</Text> </TouchableOpacity> ); if (loading) { return ( <View style={styles.center}> <ActivityIndicator size="large" color="#007AFF" /> </View> ); } if (error) { return ( <View style={styles.center}> <Text style={styles.error}>错误: {error}</Text> <TouchableOpacity style={styles.button} onPress={fetchPosts}> <Text style={styles.buttonText}>重试</Text> </TouchableOpacity> </View> ); } return ( <View style={styles.container}> <FlatList data={posts} renderItem={renderPost} keyExtractor={(item) => item.id.toString()} refreshing={loading} onRefresh={fetchPosts} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, center: { flex: 1, justifyContent: 'center', alignItems: 'center', }, postItem: { backgroundColor: 'white', padding: 15, marginHorizontal: 15, marginVertical: 5, borderRadius: 8, shadowColor: '#000', shadowOffset: { width: 0, height: 1, }, shadowOpacity: 0.22, shadowRadius: 2.22, elevation: 3, }, postTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 5, }, postExcerpt: { fontSize: 14, color: '#666', }, error: { color: '#FF3B30', fontSize: 16, marginBottom: 20, }, button: { backgroundColor: '#007AFF', padding: 15, borderRadius: 8, }, buttonText: { color: 'white', fontSize: 16, fontWeight: 'bold', }, });

🛠️ 原生模块集成

相机功能

# 安装相机库 npm install react-native-camera
// src/components/CameraComponent.js import React, { useState } from 'react'; import { View, TouchableOpacity, Text, StyleSheet } from 'react-native'; import { RNCamera } from 'react-native-camera'; export default function CameraComponent() { const [camera, setCamera] = useState(null); const takePicture = async () => { if (camera) { try { const options = { quality: 0.5, base64: true }; const data = await camera.takePictureAsync(options); console.log('Photo taken:', data.uri); } catch (error) { console.error('Camera error:', error); } } }; return ( <View style={styles.container}> <RNCamera ref={(ref) => setCamera(ref)} style={styles.camera} type={RNCamera.Constants.Type.back} flashMode={RNCamera.Constants.FlashMode.off} androidCameraPermissionOptions={{ title: '相机权限', message: '需要相机权限来拍照', buttonPositive: '确定', buttonNegative: '取消', }} > <View style={styles.buttonContainer}> <TouchableOpacity onPress={takePicture} style={styles.captureButton}> <Text style={styles.captureText}>拍照</Text> </TouchableOpacity> </View> </RNCamera> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, }, camera: { flex: 1, }, buttonContainer: { flex: 1, backgroundColor: 'transparent', flexDirection: 'row', justifyContent: 'center', alignItems: 'flex-end', marginBottom: 20, }, captureButton: { backgroundColor: '#007AFF', padding: 15, borderRadius: 50, width: 80, height: 80, justifyContent: 'center', alignItems: 'center', }, captureText: { color: 'white', fontSize: 14, fontWeight: 'bold', }, });

📖 学习资源

官方文档

实用工具和库

  • Expo: 开发工具和服务
  • React Navigation: 导航库
  • Redux Toolkit: 状态管理
  • React Native Elements: UI 组件库
  • React Native Vector Icons: 图标库

🔍 调试工具

  • React Native Debugger: 调试工具
  • Flipper: 移动应用调试平台
  • Metro: JavaScript 打包工具

最后更新: 2024年

最近更新:12/9/2025, 2:17:55 AM