目录
第一部分:React Native 入门
学习目标
-
了解 React Native 的基本概念和开发环境搭建。
-
能够创建并运行第一个 React Native 应用。
内容
-
React Native 简介
-
什么是 React Native
-
React Native 与原生开发对比
-
React Native 的优缺点
-
-
开发环境搭建
-
Node.js 和 npm 的安装
-
React Native CLI 和 Expo 的安装与使用
-
Android Studio 和 Xcode 配置
-
模拟器和真机调试环境搭建
-
-
第一个 React Native 应用
-
创建项目
-
项目结构解析
-
简单的页面编写和运行
-
实践环节
-
搭建开发环境并运行第一个应用。
-
修改默认页面,添加简单的图片或文本、按钮。
第二部分:React Native 基础
学习目标
-
掌握 React Native 的核心组件和布局方式。
-
能够实现基本的页面导航和参数传递。
内容
-
核心组件
-
Text、View、Image、Button 等组件的使用
-
ScrollView 和 FlatList 组件
-
SectionList 和 VirtualizedList
-
-
样式与布局
-
Flexbox 布局
-
样式表的使用(StyleSheet)
-
尺寸与适配
-
-
导航
-
React Navigation 的安装与使用
-
Stack Navigator、Tab Navigator 和 Drawer Navigator
-
参数传递与深度链接
-
实践环节
-
创建一个包含多个页面的应用,使用导航实现页面跳转。
-
使用 Flexbox 布局实现一个简单的用户信息展示页面。
第三部分:React Native 核心功能
学习目标
-
掌握状态管理和数据通信的核心技术。
-
能够集成设备功能(如相机、地图、推送通知)。
内容
-
状态管理
-
useState 和 useReducer 的使用
-
Redux 和 Redux Toolkit 集成
-
MobX 和 Zustand 状态管理
-
-
数据通信
-
Fetch 和 Axios 请求数据
-
数据缓存(AsyncStorage 和 MMKV)
-
数据库(SQLite 和 Realm)
-
-
设备功能
-
使用 Camera 和 Media API
-
Geolocation 与地图集成
-
推送通知(Firebase、OneSignal)
-
实践环节
-
实现一个简单的天气应用,集成地图和地理位置功能。
-
使用 Redux 管理购物车状态。
第四部分:React Native 进阶开发
学习目标
-
掌握自定义组件、动画和性能优化技术。
-
能够开发原生模块并与 React Native 交互。
内容
-
自定义组件
-
创建高复用组件
-
使用 PropTypes 和 TypeScript 检测类型
-
-
动画
-
Animated API 的使用
-
React Native Reanimated
-
手势与交互(React Native Gesture Handler)
-
-
性能优化
-
避免性能陷阱(渲染优化、PureComponent)
-
使用 Hermes 引擎
-
图片和资源的优化
-
-
原生模块
-
自定义原生模块
-
原生模块与 React Native 交互
-
使用 Native Modules 和 Native UI Components
-
实践环节
-
实现一个自定义下拉刷新组件。
-
使用 Reanimated 实现一个复杂的动画效果。
第五部分:React Native 案例实战
学习目标
-
通过实战项目巩固所学知识,提升工程能力。
-
能够独立开发中小型 React Native 应用。
内容
-
小型案例
-
ToDo 应用
-
计时器
-
-
中型案例
-
电商应用(商品列表、购物车)
-
新闻类应用(API 数据加载与显示)
-
-
大型案例
-
即时聊天应用
-
视频播放和上传应用
-
实践环节
-
分组完成一个中型或大型项目,模拟真实开发流程。
-
使用 Git 进行版本控制,使用项目管理工具(如 Jira)分配任务。
第六部分:未来趋势与学习建议
学习目标
-
了解 React Native 的最新趋势和扩展学习方向。
-
掌握持续学习和职业发展的方法。
内容
-
最新功能和趋势
-
Fabric 新架构
-
Turbo Modules
-
React Native 和 Flutter 的对比
-
-
学习资源
-
官方文档
-
社区论坛
-
开源项目和实战案例
-
-
职业发展建议
-
如何准备 React Native 开发岗位的面试
-
构建个人技术博客或开源项目
-
推荐后续学习方向(如前端工程化、移动端性能优化)
-
附录
React Native 的适配难点、疑点、兼容性问题及解决方案
-
跨平台样式差异
-
设备尺寸和屏幕适配
-
导航的兼容性问题
-
性能问题
-
原生模块的兼容性
-
网络请求和缓存问题
-
Debug 与错误处理
前端体系书籍:
第一部分:React Native 入门
学习目标
-
了解 React Native 的基本概念
-
理解 React Native 的核心思想及其与原生开发的区别。
-
掌握 React Native 的优缺点,明确其适用场景。
-
-
开发环境搭建
-
能够独立完成 React Native 开发环境的搭建。
-
熟悉常用工具(如 Node.js、npm、React Native CLI、Expo)的安装与配置。
-
-
创建并运行第一个 React Native 应用
-
掌握 React Native 项目的创建流程。
-
理解项目结构,能够编写并运行简单的页面。
-
1. React Native 简介
1.1 什么是 React Native
-
定义:
React Native 是 Facebook 于 2015 年开源的跨平台移动应用开发框架。它基于 React(一个用于构建用户界面的 JavaScript 库)和 JavaScript,允许开发者使用相同的代码库构建 iOS 和 Android 应用。 -
核心思想:
-
Learn Once, Write Anywhere:学习一次,编写多平台应用。
-
声明式 UI:通过组件化的方式构建用户界面。
-
原生渲染:使用原生组件而非 WebView,提供接近原生的性能。
-
-
工作原理:
React Native 通过 JavaScript 与原生平台通信,将 JavaScript 代码转换为原生组件。例如,React Native 的<View>
组件在 iOS 上会被转换为UIView
,在 Android 上会被转换为android.view.View
。
1.2 React Native 与原生开发对比
-
原生开发:
-
iOS:使用 Swift/Objective-C 和 Xcode。
-
Android:使用 Kotlin/Java 和 Android Studio。
-
优点:
-
性能最优,功能支持最全面。
-
直接访问平台特性(如相机、传感器)。
-
-
缺点:
-
需要维护两套代码,开发成本高。
-
开发周期长,学习曲线陡峭。
-
-
-
React Native:
-
优点:
-
跨平台开发,节省时间和成本。
-
基于 JavaScript,学习曲线较低。
-
热更新支持,无需重新发布应用。
-
-
缺点:
-
性能略低于原生,尤其在复杂动画和计算密集型任务中。
-
部分原生功能需要依赖第三方库或自定义原生模块。
-
-
1.3 React Native 的优缺点
-
优点:
-
跨平台开发:
-
使用相同的代码库开发 iOS 和 Android 应用,减少开发成本。
-
-
开发效率高:
-
基于 JavaScript,前端开发者可以快速上手。
-
支持热更新,实时预览代码修改。
-
-
社区活跃:
-
拥有庞大的开发者社区和丰富的第三方库支持。
-
-
接近原生的性能:
-
使用原生组件渲染,性能优于基于 WebView 的框架(如 Cordova)。
-
-
-
缺点:
-
性能略低于原生:
-
在复杂动画或计算密集型任务中,性能可能不如原生开发。
-
-
依赖第三方库:
-
部分原生功能(如推送通知、地图)需要依赖第三方库。
-
-
调试复杂:
-
跨平台调试可能比原生开发更复杂。
-
-
2. 开发环境搭建
2.1 Node.js 和 npm 的安装
-
Node.js:
React Native 的运行环境依赖 Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时,允许在服务器端运行 JavaScript 代码。-
安装步骤:
-
访问 Node.js 官网。
-
下载并安装最新 LTS 版本(推荐使用 nvm 管理多版本)。
-
安装完成后,通过以下命令验证安装:
node -v # 查看 Node.js 版本 npm -v # 查看 npm 版本
-
-
nvm(Node Version Manager):
用于管理多个 Node.js 版本,适合需要切换版本的开发者。-
安装命令(macOS/Linux):
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
-
常用命令:
nvm install 18 # 安装 Node.js 18.x nvm use 18 # 使用 Node.js 18.x
-
-
-
npm:
npm 是 Node.js 的包管理工具,用于安装和管理 JavaScript 库。-
常用命令:
npm install -g <package> # 全局安装包 npm install <package> # 本地安装包 npm update <package> # 更新包 npm uninstall <package> # 卸载包
-
2.2 React Native CLI 和 Expo 的安装与使用
-
React Native CLI:
React Native 官方提供的命令行工具,适合需要深度定制原生代码的项目。-
安装命令:
npm install -g react-native-cli
-
创建项目:
npx react-native init MyFirstApp
-
运行项目:
npx react-native run-android # 运行 Android 项目 npx react-native run-ios # 运行 iOS 项目
-
-
Expo:
Expo 是一个基于 React Native 的开发平台,提供了一套工具和服务,简化了开发流程。-
安装命令:
npm install -g expo-cli
-
创建项目:
expo init MyFirstApp
-
运行项目:
expo start
-
优点:
-
无需配置原生环境,适合快速原型开发。
-
提供丰富的 API 和组件(如相机、地图)。
-
-
2.3 Android Studio 和 Xcode 配置
-
Android Studio:
Android 开发的官方 IDE,用于配置 Android 开发环境。-
安装步骤:
-
下载并安装 Android Studio。
-
安装 Android SDK 和模拟器:
-
打开 Android Studio,选择 "SDK Manager"。
-
安装最新版本的 Android SDK 和 Build Tools。
-
配置环境变量(如
ANDROID_HOME
)。
-
-
创建模拟器:
-
打开 Android Studio,选择 "AVD Manager"。
-
创建一个新的虚拟设备(如 Pixel 5)。
-
启动模拟器。
-
-
-
Xcode:
iOS 开发的官方 IDE,用于配置 iOS 开发环境。-
安装步骤:
-
访问 Mac App Store。
-
下载并安装 Xcode。
-
打开 Xcode,同意许可协议并安装额外组件。
-
-
创建模拟器:
-
打开 Xcode,选择 "Window" -> "Devices and Simulators"。
-
创建一个新的模拟器(如 iPhone 14)。
-
启动模拟器。
-
-
2.4 模拟器和真机调试环境搭建
-
模拟器:
-
Android:使用 Android Studio 的 AVD Manager 创建模拟器。
-
iOS:使用 Xcode 的 Simulator。
-
-
真机调试:
-
Android:
-
通过 USB 连接设备。
-
启用开发者模式(连续点击 "设置" -> "关于手机" -> "版本号")。
-
启用 USB 调试("设置" -> "开发者选项" -> "USB 调试")。
-
-
iOS:
-
通过 USB 连接设备。
-
使用 Xcode 配置设备并安装开发证书。
-
-
3. 第一个 React Native 应用
3.1 创建项目
在完成开发环境搭建后,接下来就是创建并运行第一个 React Native 应用。React Native 提供了两种创建项目的方式:React Native CLI 和 Expo。以下是详细步骤:
3.1.1 使用 React Native CLI 创建项目
React Native CLI 是官方提供的命令行工具,适合需要深度定制原生代码的项目。
-
安装 React Native CLI(如果尚未安装):
npm install -g react-native-cli
-
创建项目:
使用以下命令创建一个新的 React Native 项目:npx react-native init MyFirstApp
-
MyFirstApp
是项目名称,可以根据需要修改。 -
创建完成后,进入项目目录:
cd MyFirstApp
-
-
项目结构:
创建完成后,项目目录结构如下:MyFirstApp/ ├── android/ # Android 原生代码 ├── ios/ # iOS 原生代码 ├── node_modules/ # 项目依赖的第三方库 ├── src/ # 源代码目录(可选) ├── App.js # 应用的入口文件 ├── package.json # 项目的依赖和脚本配置 └── ... # 其他配置文件
3.1.2 使用 Expo 创建项目
Expo 是一个基于 React Native 的开发平台,适合快速原型开发。
-
安装 Expo CLI(如果尚未安装):
npm install -g expo-cli
-
创建项目:
使用以下命令创建一个新的 Expo 项目:expo init MyFirstApp
-
选择模板(推荐选择 "blank" 空白模板)。
-
创建完成后,进入项目目录:
cd MyFirstApp
-
-
项目结构:
创建完成后,项目目录结构如下:MyFirstApp/ ├── assets/ # 静态资源(如图片、字体) ├── node_modules/ # 项目依赖的第三方库 ├── src/ # 源代码目录(可选) ├── App.js # 应用的入口文件 ├── package.json # 项目的依赖和脚本配置 └── ... # 其他配置文件
3.2 项目结构解析
无论是使用 React Native CLI 还是 Expo 创建的项目,其核心结构是相似的。以下是关键文件和目录的详细说明:
3.2.1 核心文件
-
App.js
:-
应用的入口文件,默认包含一个简单的 React 组件。
-
开发者可以在此文件中编写应用的 UI 和逻辑。
-
-
package.json
:-
项目的配置文件,包含项目的依赖和脚本命令。
-
例如:
{ "name": "MyFirstApp", "version": "1.0.0", "scripts": { "start": "react-native start", "android": "react-native run-android", "ios": "react-native run-ios" }, "dependencies": { "react": "18.2.0", "react-native": "0.71.0" } }
-
-
node_modules/
:-
存放项目依赖的第三方库。
-
通过
npm install
或yarn install
安装依赖时生成。
-
3.2.2 原生代码目录
-
android/
:-
包含 Android 原生代码和配置文件。
-
例如:
build.gradle
、AndroidManifest.xml
。
-
-
ios/
:-
包含 iOS 原生代码和配置文件。
-
例如:
AppDelegate.m
、Info.plist
。
-
3.2.3 其他目录
-
src/
:-
可选的源代码目录,用于存放组件、页面和工具函数。
-
例如:
src/ ├── components/ # 可复用组件 ├── screens/ # 页面组件 └── utils/ # 工具函数
-
-
assets/
:-
存放静态资源(如图片、字体)。
-
在 Expo 项目中默认存在,React Native CLI 项目可手动创建。
-
3.3 简单的页面编写和运行
在创建项目并了解项目结构后,接下来编写一个简单的页面并运行应用。
3.3.1 修改 App.js
打开 App.js
,编写一个简单的页面:
import React from 'react'; import { View, Text, StyleSheet, Button } from 'react-native'; const App = () => { const handlePress = () => { alert('Hello, React Native!'); }; return ( <View style={styles.container}> <Text style={styles.text}>Welcome to React Native!</Text> <Button title="Click Me" onPress={handlePress} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', }, text: { fontSize: 20, fontWeight: 'bold', marginBottom: 20, }, }); export default App;
3.3.2 运行项目
-
React Native CLI:
-
启动 Metro Bundler(JavaScript 打包工具):
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
-
-
Expo:
-
启动开发服务器:
expo start
-
使用 Expo Go 应用扫描二维码,在真机或模拟器上运行项目。
-
3.3.3 运行效果
-
页面显示一个居中文本 "Welcome to React Native!" 和一个按钮。
-
点击按钮后,弹出提示框 "Hello, React Native!"。
4. 实践环节
-
创建项目:
-
使用 React Native CLI 或 Expo 创建一个新项目。
-
-
修改页面:
-
修改
App.js
,添加一个图片组件、文本及按钮并设置样式。
-
-
运行项目:
-
在模拟器或真机上运行项目,查看效果。
-
4.1 创建项目
在实践环节中,学员将通过实际操作创建一个 React Native 项目,并运行在模拟器或真机上。以下是详细步骤:
4.1.1 使用 React Native CLI 创建项目
-
安装 React Native CLI(如果尚未安装):
npm install -g react-native-cli
-
创建项目:
使用以下命令创建一个新的 React Native 项目:npx react-native init MyFirstApp
-
MyFirstApp
是项目名称,可以根据需要修改。 -
创建完成后,进入项目目录:
cd MyFirstApp
-
-
项目结构:
创建完成后,项目目录结构如下:MyFirstApp/ ├── android/ # Android 原生代码 ├── ios/ # iOS 原生代码 ├── node_modules/ # 项目依赖的第三方库 ├── App.js # 应用的入口文件 ├── package.json # 项目的依赖和脚本配置 └── ... # 其他配置文件
4.1.2 使用 Expo 创建项目
-
安装 Expo CLI(如果尚未安装):
npm install -g expo-cli
-
创建项目:
使用以下命令创建一个新的 Expo 项目:expo init MyFirstApp
-
选择模板(推荐选择 "blank" 空白模板)。
-
创建完成后,进入项目目录:
cd MyFirstApp
-
-
项目结构:
创建完成后,项目目录结构如下:MyFirstApp/ ├── assets/ # 静态资源(如图片、字体) ├── node_modules/ # 项目依赖的第三方库 ├── App.js # 应用的入口文件 ├── package.json # 项目的依赖和脚本配置 └── ... # 其他配置文件
4.2 修改页面
在创建项目后,学员需要修改 App.js
,添加一个图片组件、文本及按钮,并设置样式。
4.2.1 修改 App.js
打开 App.js
,编写以下代码:
import React from 'react'; import { View, Text, Image, StyleSheet, Button, Alert } from 'react-native'; const App = () => { const handlePress = () => { Alert.alert('Button Pressed', 'You clicked the button!'); }; return ( <View style={styles.container}> <Text style={styles.title}>Welcome to MyFirstApp!</Text> <Image source={require('./assets/logo.png')} // 替换为你的图片路径 style={styles.image} /> <Text style={styles.subtitle}>This is a simple React Native app.</Text> <Button title="Click Me" onPress={handlePress} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', marginBottom: 20, color: '#333', }, subtitle: { fontSize: 16, color: '#666', marginBottom: 20, }, image: { width: 150, height: 150, marginBottom: 20, borderRadius: 75, // 圆形图片 }, }); export default App;
4.2.2 添加图片资源
-
在项目根目录下创建
assets/
文件夹(如果不存在)。 -
将图片文件(如
logo.png
)放入assets/
文件夹中。 -
在代码中通过
require('./assets/logo.png')
引用图片。
4.3 运行项目
在完成页面修改后,学员需要在模拟器或真机上运行项目,查看效果。
4.3.1 使用 React Native CLI 运行项目
-
启动 Metro Bundler:
在项目根目录下运行以下命令:npx react-native start
-
运行 Android 项目:
打开一个新的终端窗口,运行以下命令:npx react-native run-android
-
运行 iOS 项目:
打开一个新的终端窗口,运行以下命令:npx react-native run-ios
4.3.2 使用 Expo 运行项目
-
启动开发服务器:
在项目根目录下运行以下命令:expo start
-
运行项目:
-
在浏览器中打开 Expo Dev Tools。
-
使用 Expo Go 应用扫描二维码,在真机或模拟器上运行项目。
-
4.3.3 运行效果
-
页面显示一个居中标题 "Welcome to MyFirstApp!"。
-
显示一张圆形图片。
-
显示一段副标题 "This is a simple React Native app."。
-
显示一个按钮,点击后弹出提示框 "You clicked the button!"。
评估标准
-
能够独立创建 React Native 项目。
-
理解项目结构,并能对默认页面进行简单修改。
-
能够运行项目并查看效果。
通过以上内容的学习,读者可以掌握 React Native 的基本概念和开发环境搭建,为后续学习打下坚实基础。
第二部分:React Native 基础
学习目标
-
掌握 React Native 的核心组件和布局方式。
-
能够实现基本的页面导航和参数传递。
内容
-
核心组件
-
Text、View、Image、Button 等组件的使用
-
ScrollView 和 FlatList 组件
-
SectionList 和 VirtualizedList
-
-
样式与布局
-
Flexbox 布局
-
样式表的使用(StyleSheet)
-
尺寸与适配
-
-
导航
-
React Navigation 的安装与使用
-
Stack Navigator、Tab Navigator 和 Drawer Navigator
-
参数传递与深度链接
-
实践环节
-
创建一个包含多个页面的应用,使用导航实现页面跳转。
-
使用 Flexbox 布局实现一个简单的用户信息展示页面。
学习目标
-
掌握 React Native 的核心组件和布局方式:
-
理解并熟练使用常用组件(如
Text
、View
、Image
、Button
)。 -
掌握列表组件(如
ScrollView
、FlatList
、SectionList
)的使用场景和区别。
-
-
能够实现基本的页面导航和参数传递:
-
使用
React Navigation
实现页面跳转和参数传递。
-
-
能够实现基本的页面导航和参数传递:
-
使用
Stack Navigator
、Tab Navigator
和Drawer Navigator
实现页面跳转。 -
掌握参数传递和深度链接的使用。
-
1. 核心组件
1.1 Text、View、Image、Button 等组件的使用
React Native 提供了一系列核心组件,用于构建用户界面。以下是常用组件的详细说明:
1.1.1 Text 组件
-
功能:用于显示文本内容。
-
常用属性:
-
style
:设置文本样式(如字体大小、颜色)。 -
numberOfLines
:限制文本行数。 -
onPress
:点击事件回调。
-
-
示例:
import React from 'react'; import { Text, StyleSheet } from 'react-native'; const App = () => { return ( <Text style={styles.text}> Hello, React Native! </Text> ); }; const styles = StyleSheet.create({ text: { fontSize: 20, fontWeight: 'bold', color: 'blue', }, }); export default App;
1.1.2 View 组件
-
功能:用于布局的容器组件,类似于 HTML 中的
div
。 -
常用属性:
-
style
:设置布局样式(如宽度、高度、背景颜色)。 -
onLayout
:获取布局尺寸的回调。
-
-
示例:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Text style={styles.text}>Inside a View</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', }, text: { fontSize: 18, }, }); export default App;
1.1.3 Image 组件
-
功能:用于显示图片。
-
常用属性:
-
source
:图片资源(本地或远程)。 -
style
:设置图片样式(如宽度、高度、圆角)。 -
resizeMode
:图片缩放模式(如cover
、contain
)。
-
-
示例:
import React from 'react'; import { View, Image, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Image source={require('./assets/logo.png')} style={styles.image} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, image: { width: 200, height: 200, borderRadius: 100, }, }); export default App;
1.1.4 Button 组件
-
功能:用于触发操作的按钮。
-
常用属性:
-
title
:按钮显示的文本。 -
onPress
:点击事件回调。 -
color
:按钮背景颜色。
-
-
示例:
import React from 'react'; import { View, Button, Alert } from 'react-native'; const App = () => { return ( <View style={{ flex: 1, justifyContent: 'center', padding: 20 }}> <Button title="Click Me" onPress={() => Alert.alert('Button Pressed')} /> </View> ); }; export default App;
1.2 ScrollView 和 FlatList 组件
-
ScrollView:
-
用于显示可滚动的内容区域。
-
适合内容较少的情况,因为会一次性渲染所有子组件。
-
-
FlatList:
-
用于显示长列表,支持懒加载和性能优化。
-
适合内容较多的情况,只渲染可见区域的内容。
-
-
示例:
import React from 'react'; import { FlatList, Text, View, StyleSheet } from 'react-native'; const data = [ { id: '1', text: 'Item 1' }, { id: '2', text: 'Item 2' }, { id: '3', text: 'Item 3' }, ]; const App = () => { return ( <FlatList data={data} renderItem={({ item }) => ( <View style={styles.item}> <Text style={styles.text}>{item.text}</Text> </View> )} keyExtractor={(item) => item.id} /> ); }; const styles = StyleSheet.create({ item: { padding: 20, borderBottomWidth: 1, borderBottomColor: '#ccc', }, text: { fontSize: 18, }, }); export default App;
1.3 SectionList 和 VirtualizedList
-
SectionList:
-
用于显示分组的列表数据。
-
适合需要分组显示的场景(如通讯录)。
-
-
VirtualizedList:
-
是
FlatList
和SectionList
的底层实现。 -
提供更灵活的列表渲染控制。
-
2. 样式与布局
2.1 Flexbox 布局
-
Flexbox 是 React Native 中用于布局的核心技术,类似于 CSS 中的 Flexbox。
-
常用属性:
-
flex
:定义组件的伸缩比例。 -
flexDirection
:定义主轴方向(row
或column
)。 -
justifyContent
:定义主轴对齐方式(如center
、space-between
)。 -
alignItems
:定义交叉轴对齐方式(如center
、flex-start
)。
-
-
示例:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <View style={styles.box1} /> <View style={styles.box2} /> <View style={styles.box3} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 20, }, box1: { width: 50, height: 50, backgroundColor: 'red', }, box2: { width: 50, height: 50, backgroundColor: 'green', }, box3: { width: 50, height: 50, backgroundColor: 'blue', }, }); export default App;
2.2 样式表的使用(StyleSheet)
-
StyleSheet 用于定义组件的样式,类似于 CSS。
-
优点:
-
提高代码可读性。
-
支持类型检查和性能优化。
-
-
示例:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const App = () => { return ( <View style={styles.container}> <Text style={styles.text}>Hello, StyleSheet!</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 20, fontWeight: 'bold', color: 'purple', }, }); export default App;
2.3 尺寸与适配
-
Dimensions:用于获取屏幕尺寸。
-
PixelRatio:用于处理像素密度问题。
-
示例:
import React from 'react'; import { View, Text, Dimensions, StyleSheet } from 'react-native'; const { width, height } = Dimensions.get('window'); const App = () => { return ( <View style={styles.container}> <Text style={styles.text}> Screen Width: {width}, Height: {height} </Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 18, }, }); export default App;
3. 导航
在移动应用开发中,导航是实现页面跳转和用户交互的核心功能。React Native 提供了多种导航解决方案,其中最流行的是 React Navigation。以下是 React Navigation 的详细讲解:
3.1 React Navigation 的安装与使用
3.1.1 安装 React Navigation
React Navigation 是一个基于 JavaScript 的导航库,支持多种导航模式。以下是安装步骤:
-
安装核心包:
npm install @react-navigation/native
-
安装依赖包:
React Navigation 依赖于一些原生模块,需要安装以下包:npm install react-native-screens react-native-safe-area-context
-
安装导航器:
根据需求安装不同的导航器:-
Stack Navigator:
npm install @react-navigation/stack
-
Tab Navigator:
npm install @react-navigation/bottom-tabs
-
Drawer Navigator:
npm install @react-navigation/drawer
-
-
链接原生依赖(React Native CLI 项目):
npx react-native link
3.1.2 配置导航器
在项目中配置导航器,以下是基本步骤:
-
导入导航器:
import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack';
-
创建导航器:
const Stack = createStackNavigator();
-
定义页面组件:
const HomeScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home Screen</Text> </View> ); }; const DetailsScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details Screen</Text> </View> ); };
-
配置导航器:
const App = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> </NavigationContainer> ); };
3.2 Stack Navigator、Tab Navigator 和 Drawer Navigator
3.2.1 Stack Navigator
-
功能:用于实现页面堆栈导航,支持页面跳转和返回。
-
常用场景:
-
页面之间的跳转(如从首页跳转到详情页)。
-
支持页面返回和传递参数。
-
-
示例:
import React from 'react'; import { Button, View, Text } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; const Stack = createStackNavigator(); const HomeScreen = ({ navigation }) => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home Screen</Text> <Button title="Go to Details" onPress={() => navigation.navigate('Details')} /> </View> ); }; const DetailsScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Details Screen</Text> </View> ); }; const App = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
3.2.2 Tab Navigator
-
功能:用于实现底部或顶部标签导航,支持快速切换页面。
-
常用场景:
-
底部导航栏(如首页、消息、个人中心)。
-
顶部标签栏(如分类、推荐、热门)。
-
-
示例:
import React from 'react'; import { Text, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; const Tab = createBottomTabNavigator(); const HomeScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home Screen</Text> </View> ); }; const SettingsScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings Screen</Text> </View> ); }; const App = () => { return ( <NavigationContainer> <Tab.Navigator> <Tab.Screen name="Home" component={HomeScreen} /> <Tab.Screen name="Settings" component={SettingsScreen} /> </Tab.Navigator> </NavigationContainer> ); }; export default App;
3.2.3 Drawer Navigator
-
功能:用于实现侧边栏导航,支持滑动打开菜单。
-
常用场景:
-
侧边栏菜单(如设置、帮助、关于)。
-
复杂的应用导航结构。
-
-
示例:
import React from 'react'; import { Button, View, Text } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createDrawerNavigator } from '@react-navigation/drawer'; const Drawer = createDrawerNavigator(); const HomeScreen = ({ navigation }) => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Home Screen</Text> <Button title="Open Drawer" onPress={() => navigation.openDrawer()} /> </View> ); }; const SettingsScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Settings Screen</Text> </View> ); }; const App = () => { return ( <NavigationContainer> <Drawer.Navigator> <Drawer.Screen name="Home" component={HomeScreen} /> <Drawer.Screen name="Settings" component={SettingsScreen} /> </Drawer.Navigator> </NavigationContainer> ); }; export default App;
3.3 参数传递与深度链接
3.3.1 参数传递
-
功能:在页面跳转时传递参数,用于动态显示内容。
-
示例:
const HomeScreen = ({ navigation }) => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Button title="Go to Details" onPress={() => navigation.navigate('Details', { itemId: 86 })} /> </View> ); }; const DetailsScreen = ({ route }) => { const { itemId } = route.params; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Item ID: {itemId}</Text> </View> ); };
3.3.2 深度链接
-
功能:通过 URL 打开应用的特定页面。
-
配置步骤:
-
在
App.js
中配置深度链接:const linking = { prefixes: ['myapp://'], config: { screens: { Home: 'home', Details: 'details/:itemId', }, }, }; const App = () => { return ( <NavigationContainer linking={linking}> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Details" component={DetailsScreen} /> </Stack.Navigator> </NavigationContainer> ); };
-
在浏览器或终端中打开链接:
myapp://details/42
-
4. 实践环节
在实践环节中,学员将通过实际操作创建一个包含多个页面的应用,并使用导航实现页面跳转。同时,学员将使用 Flexbox 布局实现一个简单的用户信息展示页面。
4.1 创建一个包含多个页面的应用,使用导航实现页面跳转
4.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init MultiPageApp
或
expo init MultiPageApp
-
安装 React Navigation:
安装 React Navigation 及其依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack
4.1.2 创建页面组件
在 src/screens/
目录下创建以下页面组件:
-
HomeScreen.js:
import React from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; const HomeScreen = ({ navigation }) => { return ( <View style={styles.container}> <Text style={styles.title}>Home Screen</Text> <Button title="Go to Profile" onPress={() => navigation.navigate('Profile')} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, title: { fontSize: 24, marginBottom: 20, }, }); export default HomeScreen;
-
ProfileScreen.js:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const ProfileScreen = () => { return ( <View style={styles.container}> <Text style={styles.title}>Profile Screen</Text> <Text style={styles.text}>Welcome to your profile!</Text> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, title: { fontSize: 24, marginBottom: 20, }, text: { fontSize: 16, }, }); export default ProfileScreen;
4.1.3 配置导航器
在 App.js
中配置 Stack Navigator:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import HomeScreen from './src/screens/HomeScreen'; import ProfileScreen from './src/screens/ProfileScreen'; const Stack = createStackNavigator(); const App = () => { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Profile" component={ProfileScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
4.1.4 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
4.1.5 运行效果
-
首页显示 "Home Screen" 和一个按钮。
-
点击按钮后跳转到 "Profile Screen",显示 "Welcome to your profile!"。
4.2 使用 Flexbox 布局实现一个简单的用户信息展示页面
4.2.1 创建用户信息页面
在 src/screens/
目录下创建 UserProfileScreen.js
:
import React from 'react'; import { View, Text, Image, StyleSheet } from 'react-native'; const UserProfileScreen = () => { return ( <View style={styles.container}> <Image source={require('../assets/avatar.png')} // 替换为你的图片路径 style={styles.avatar} /> <Text style={styles.name}>John Doe</Text> <Text style={styles.bio}>Software Developer | React Native Enthusiast</Text> <View style={styles.details}> <Text style={styles.detailText}>Email: john.doe@example.com</Text> <Text style={styles.detailText}>Location: New York, USA</Text> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, backgroundColor: '#f5f5f5', }, avatar: { width: 150, height: 150, borderRadius: 75, marginBottom: 20, }, name: { fontSize: 24, fontWeight: 'bold', marginBottom: 10, }, bio: { fontSize: 16, color: '#666', marginBottom: 20, textAlign: 'center', }, details: { width: '100%', padding: 20, backgroundColor: '#fff', borderRadius: 10, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, elevation: 3, }, detailText: { fontSize: 16, marginBottom: 10, }, }); export default UserProfileScreen;
4.2.2 添加图片资源
-
在项目根目录下创建
assets/
文件夹(如果不存在)。 -
将图片文件(如
avatar.png
)放入assets/
文件夹中。 -
在代码中通过
require('../assets/avatar.png')
引用图片。
4.2.3 配置导航器
在 App.js
中添加 UserProfileScreen
:
import UserProfileScreen from './src/screens/UserProfileScreen'; const App = () => { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Profile" component={ProfileScreen} /> <Stack.Screen name="UserProfile" component={UserProfileScreen} /> </Stack.Navigator> </NavigationContainer> ); };
4.2.4 运行效果
-
页面显示用户头像、姓名、简介和详细信息。
-
使用 Flexbox 布局实现居中显示和卡片式设计。
评估标准
-
导航功能:
-
能够实现页面跳转并正确显示目标页面。
-
-
Flexbox 布局:
-
能够使用 Flexbox 实现页面布局,确保内容居中且美观。
-
-
代码结构:
-
代码结构清晰,组件和样式分离。
-
通过以上内容的学习,读者可以掌握 React Native 基础 的具体功能,包括核心组件、样式布局、导航等相关功能的开发,能够实现页面基础组件、样式布局、页面导航、参数传递和深度链接功能。
第三部分:React Native 核心功能
学习目标
-
掌握状态管理和数据通信的核心技术。
-
能够集成设备功能(如相机、地图、推送通知)。
内容
-
状态管理
-
useState 和 useReducer 的使用
-
Redux 和 Redux Toolkit 集成
-
MobX 和 Zustand 状态管理
-
-
数据通信
-
Fetch 和 Axios 请求数据
-
数据缓存(AsyncStorage 和 MMKV)
-
数据库(SQLite 和 Realm)
-
-
设备功能
-
使用 Camera 和 Media API
-
Geolocation 与地图集成
-
推送通知(Firebase、OneSignal)
-
实践环节
-
实现一个简单的天气应用,集成地图和地理位置功能。
-
使用 Redux 管理购物车状态。
学习目标
-
掌握状态管理和数据通信的核心技术:
-
理解并熟练使用
useState
、useReducer
、Redux
和MobX
进行状态管理。 -
掌握数据通信技术(如
Fetch
、Axios
、AsyncStorage
和SQLite
)。
-
-
能够集成设备功能:
-
使用相机、地图和推送通知等设备功能。
-
1. 状态管理
1.1 useState 和 useReducer 的使用
React 提供了 useState
和 useReducer
两个 Hook,用于在函数组件中管理状态。
1.1.1 useState
-
功能:用于管理简单的状态。
-
示例:
import React, { useState } from 'react'; import { View, Text, Button } from 'react-native'; const Counter = () => { const [count, setCount] = useState(0); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Count: {count}</Text> <Button title="Increment" onPress={() => setCount(count + 1)} /> </View> ); }; export default Counter;
1.1.2 useReducer
-
功能:用于管理复杂的状态逻辑。
-
示例:
import React, { useReducer } from 'react'; import { View, Text, Button } from 'react-native'; const initialState = { count: 0 }; const reducer = (state, action) => { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } }; const Counter = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Count: {state.count}</Text> <Button title="Increment" onPress={() => dispatch({ type: 'increment' })} /> <Button title="Decrement" onPress={() => dispatch({ type: 'decrement' })} /> </View> ); }; export default Counter;
1.2 Redux 和 Redux Toolkit 集成
Redux 是一个流行的状态管理库,适合大型应用。Redux Toolkit 是 Redux 的官方工具集,简化了 Redux 的使用。
1.2.1 安装 Redux Toolkit
npm install @reduxjs/toolkit react-redux
1.2.2 创建 Redux Store
在 src/store/
目录下创建 store.js
:
import { configureStore } from '@reduxjs/toolkit'; import counterReducer from './counterSlice'; const store = configureStore({ reducer: { counter: counterReducer, }, }); export default store;
1.2.3 创建 Slice
在 src/store/
目录下创建 counterSlice.js
:
import { createSlice } from '@reduxjs/toolkit'; const counterSlice = createSlice({ name: 'counter', initialState: { value: 0 }, reducers: { increment: (state) => { state.value += 1; }, decrement: (state) => { state.value -= 1; }, }, }); export const { increment, decrement } = counterSlice.actions; export default counterSlice.reducer;
1.2.4 在组件中使用 Redux
在 App.js
中配置 Redux Provider:
import React from 'react'; import { Provider } from 'react-redux'; import store from './src/store/store'; import Counter from './src/components/Counter'; const App = () => { return ( <Provider store={store}> <Counter /> </Provider> ); }; export default App;
在 Counter.js
中使用 Redux:
import React from 'react'; import { View, Text, Button } from 'react-native'; import { useSelector, useDispatch } from 'react-redux'; import { increment, decrement } from '../store/counterSlice'; const Counter = () => { const count = useSelector((state) => state.counter.value); const dispatch = useDispatch(); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Count: {count}</Text> <Button title="Increment" onPress={() => dispatch(increment())} /> <Button title="Decrement" onPress={() => dispatch(decrement())} /> </View> ); }; export default Counter;
1.3 MobX 和 Zustand 状态管理
-
MobX:一个响应式状态管理库,适合中小型应用。
-
Zustand:一个轻量级状态管理库,适合小型应用。
2. 数据通信
2.1 Fetch 和 Axios 请求数据
-
Fetch:浏览器原生 API,用于发送网络请求。
-
Axios:一个流行的 HTTP 客户端,支持更多功能(如拦截器)。
2.1.1 使用 Fetch
import React, { useEffect, useState } from 'react'; import { View, Text } from 'react-native'; const DataFetching = () => { const [data, setData] = useState(null); useEffect(() => { fetch('https://jsonplaceholder.typicode.com/posts/1') .then((response) => response.json()) .then((json) => setData(json)) .catch((error) => console.error(error)); }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>{data ? data.title : 'Loading...'}</Text> </View> ); }; export default DataFetching;
2.1.2 使用 Axios
-
安装 Axios:
npm install axios
-
发送请求:
import React, { useEffect, useState } from 'react'; import { View, Text } from 'react-native'; import axios from 'axios'; const DataFetching = () => { const [data, setData] = useState(null); useEffect(() => { axios.get('https://jsonplaceholder.typicode.com/posts/1') .then((response) => setData(response.data)) .catch((error) => console.error(error)); }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>{data ? data.title : 'Loading...'}</Text> </View> ); }; export default DataFetching;
2.2 数据缓存(AsyncStorage 和 MMKV)
-
AsyncStorage:React Native 提供的简单键值存储。
-
MMKV:一个高性能的键值存储库。
2.2.1 使用 AsyncStorage
-
安装 AsyncStorage:
npm install @react-native-async-storage/async-storage
-
存储和读取数据:
import React, { useEffect, useState } from 'react'; import { View, Text, Button } from 'react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; const StorageExample = () => { const [value, setValue] = useState(''); const saveData = async () => { await AsyncStorage.setItem('key', 'Hello, AsyncStorage!'); }; const loadData = async () => { const data = await AsyncStorage.getItem('key'); setValue(data); }; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>{value}</Text> <Button title="Save Data" onPress={saveData} /> <Button title="Load Data" onPress={loadData} /> </View> ); }; export default StorageExample;
2.3 数据库(SQLite 和 Realm)
-
SQLite:一个轻量级的关系型数据库。
-
Realm:一个高性能的 NoSQL 数据库。
3. 设备功能
3.1 使用 Camera 和 Media API
-
react-native-camera:用于访问设备相机。
-
react-native-video:用于播放视频。
3.1.1 使用 Camera
-
安装 react-native-camera:
npm install react-native-camera
-
拍照功能:
import React, { useRef } from 'react'; import { View, Button } from 'react-native'; import { RNCamera } from 'react-native-camera'; const CameraExample = () => { const cameraRef = useRef(null); const takePicture = async () => { if (cameraRef.current) { const options = { quality: 0.5, base64: true }; const data = await cameraRef.current.takePictureAsync(options); console.log(data.uri); } }; return ( <View style={{ flex: 1 }}> <RNCamera ref={cameraRef} style={{ flex: 1 }} type={RNCamera.Constants.Type.back} /> <Button title="Take Picture" onPress={takePicture} /> </View> ); }; export default CameraExample;
3.2 Geolocation 与地图集成
-
react-native-geolocation-service:用于获取设备位置。
-
react-native-maps:用于显示地图。
3.2.1 获取设备位置
-
安装 react-native-geolocation-service:
npm install react-native-geolocation-service
-
获取位置:
import React, { useEffect, useState } from 'react'; import { View, Text } from 'react-native'; import Geolocation from 'react-native-geolocation-service'; const LocationExample = () => { const [location, setLocation] = useState(null); useEffect(() => { Geolocation.getCurrentPosition( (position) => { setLocation(position.coords); }, (error) => { console.error(error); }, { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 } ); }, []); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Latitude: {location?.latitude}</Text> <Text>Longitude: {location?.longitude}</Text> </View> ); }; export default LocationExample;
3.3 推送通知(Firebase、OneSignal)
-
Firebase Cloud Messaging (FCM):用于发送推送通知。
-
OneSignal:一个推送通知服务平台。
3.3.1 使用 Firebase 推送通知
-
安装 Firebase:
npm install @react-native-firebase/app @react-native-firebase/messaging
-
配置 Firebase:
-
在 Firebase 控制台创建项目并下载配置文件。
-
将配置文件放入
android/app/
和ios/
目录。
-
-
接收通知:
import React, { useEffect } from 'react'; import messaging from '@react-native-firebase/messaging'; const NotificationExample = () => { useEffect(() => { const unsubscribe = messaging().onMessage(async (remoteMessage) => { console.log('Received notification:', remoteMessage); }); return unsubscribe; }, []); return null; }; export default NotificationExample;
4. 实践环节
在实践环节中,学员将通过实际操作实现一个简单的天气应用,集成地图和地理位置功能。同时,学员将使用 Redux 管理购物车状态。
4.1 实现一个简单的天气应用,集成地图和地理位置功能
4.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init WeatherApp
或
expo init WeatherApp
-
安装依赖:
安装以下依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack react-native-maps react-native-geolocation-service axios
4.1.2 创建页面组件
在 src/screens/
目录下创建以下页面组件:
-
HomeScreen.js:
import React, { useEffect, useState } from 'react'; import { View, Text, StyleSheet, ActivityIndicator } from 'react-native'; import MapView, { Marker } from 'react-native-maps'; import Geolocation from 'react-native-geolocation-service'; import axios from 'axios'; const HomeScreen = () => { const [location, setLocation] = useState(null); const [weather, setWeather] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { // 获取设备位置 Geolocation.getCurrentPosition( (position) => { const { latitude, longitude } = position.coords; setLocation({ latitude, longitude }); fetchWeather(latitude, longitude); }, (error) => { console.error(error); setLoading(false); }, { enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 } ); }, []); const fetchWeather = async (lat, lon) => { try { const apiKey = 'YOUR_OPENWEATHERMAP_API_KEY'; // 替换为你的 API Key const response = await axios.get( `https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=metric` ); setWeather(response.data); } catch (error) { console.error(error); } finally { setLoading(false); } }; if (loading) { return ( <View style={styles.container}> <ActivityIndicator size="large" color="#0000ff" /> </View> ); } return ( <View style={styles.container}> {location && ( <MapView style={styles.map} initialRegion={{ latitude: location.latitude, longitude: location.longitude, latitudeDelta: 0.0922, longitudeDelta: 0.0421, }} > <Marker coordinate={{ latitude: location.latitude, longitude: location.longitude, }} title="Your Location" /> </MapView> )} {weather && ( <View style={styles.weatherContainer}> <Text style={styles.weatherText}> {weather.name}, {weather.sys.country} </Text> <Text style={styles.weatherText}> {weather.weather[0].description} </Text> <Text style={styles.weatherText}> Temperature: {weather.main.temp}°C </Text> </View> )} </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, }, map: { flex: 1, }, weatherContainer: { position: 'absolute', bottom: 20, left: 20, right: 20, backgroundColor: 'rgba(255, 255, 255, 0.8)', padding: 10, borderRadius: 10, }, weatherText: { fontSize: 16, textAlign: 'center', }, }); export default HomeScreen;
4.1.3 配置导航器
在 App.js
中配置 Stack Navigator:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import HomeScreen from './src/screens/HomeScreen'; const Stack = createStackNavigator(); const App = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
4.1.4 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
4.1.5 运行效果
-
页面显示地图和当前位置的标记。
-
显示当前位置的天气信息(城市、天气描述、温度)。
4.2 使用 Redux 管理购物车状态
4.2.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init ShoppingCartApp
或
expo init ShoppingCartApp
-
安装 Redux Toolkit:
npm install @reduxjs/toolkit react-redux
4.2.2 创建 Redux Store
在 src/store/
目录下创建 store.js
:
import { configureStore } from '@reduxjs/toolkit'; import cartReducer from './cartSlice'; const store = configureStore({ reducer: { cart: cartReducer, }, }); export default store;
4.2.3 创建 Slice
在 src/store/
目录下创建 cartSlice.js
:
import { createSlice } from '@reduxjs/toolkit'; const cartSlice = createSlice({ name: 'cart', initialState: { items: [], }, reducers: { addItem: (state, action) => { state.items.push(action.payload); }, removeItem: (state, action) => { state.items = state.items.filter((item) => item.id !== action.payload.id); }, }, }); export const { addItem, removeItem } = cartSlice.actions; export default cartSlice.reducer;
4.2.4 在组件中使用 Redux
在 App.js
中配置 Redux Provider:
import React from 'react'; import { Provider } from 'react-redux'; import store from './src/store/store'; import CartScreen from './src/screens/CartScreen'; const App = () => { return ( <Provider store={store}> <CartScreen /> </Provider> ); }; export default App;
在 CartScreen.js
中使用 Redux:
import React from 'react'; import { View, Text, Button, FlatList, StyleSheet } from 'react-native'; import { useSelector, useDispatch } from 'react-redux'; import { addItem, removeItem } from '../store/cartSlice'; const CartScreen = () => { const cartItems = useSelector((state) => state.cart.items); const dispatch = useDispatch(); const handleAddItem = () => { const newItem = { id: Math.random().toString(), name: `Product ${cartItems.length + 1}`, price: Math.floor(Math.random() * 100), }; dispatch(addItem(newItem)); }; const handleRemoveItem = (item) => { dispatch(removeItem(item)); }; return ( <View style={styles.container}> <Button title="Add Item" onPress={handleAddItem} /> <FlatList data={cartItems} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.item}> <Text style={styles.itemText}> {item.name} - ${item.price} </Text> <Button title="Remove" onPress={() => handleRemoveItem(item)} /> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, item: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', }, itemText: { fontSize: 16, }, }); export default CartScreen;
4.2.5 运行效果
-
点击 "Add Item" 按钮,添加商品到购物车。
-
点击 "Remove" 按钮,从购物车中移除商品。
评估标准
-
天气应用:
-
能够正确获取设备位置并显示地图。
-
能够调用天气 API 并显示天气信息。
-
-
购物车应用:
-
能够使用 Redux 管理购物车状态。
-
能够实现添加和移除商品的功能。
-
通过以上内容的学习,读者可以掌握状态管理、数据通信和设备功能的核心技术,为开发复杂应用打下坚实基础。
第四部分:React Native 进阶开发
学习目标
-
掌握自定义组件、动画和性能优化技术。
-
能够开发原生模块并与 React Native 交互。
内容
-
自定义组件
-
创建高复用组件
-
使用 PropTypes 和 TypeScript 检测类型
-
-
动画
-
Animated API 的使用
-
React Native Reanimated
-
手势与交互(React Native Gesture Handler)
-
-
性能优化
-
避免性能陷阱(渲染优化、PureComponent)
-
使用 Hermes 引擎
-
图片和资源的优化
-
-
原生模块
-
自定义原生模块
-
原生模块与 React Native 交互
-
使用 Native Modules 和 Native UI Components
-
实践环节
-
实现一个自定义下拉刷新组件。
-
使用 Reanimated 实现一个复杂的动画效果。
学习目标
-
掌握自定义组件、动画和性能优化技术:
-
能够创建高复用组件并使用 PropTypes 和 TypeScript 检测类型。
-
掌握 Animated API 和 React Native Reanimated 实现复杂动画。
-
使用 React Native Gesture Handler 实现手势交互。
-
-
能够开发原生模块并与 React Native 交互:
-
创建自定义原生模块并在 JavaScript 中调用。
-
使用 Native Modules 和 Native UI Components 扩展功能。
-
1. 自定义组件
1.1 创建高复用组件
在 React Native 中,自定义组件是提高代码复用性和可维护性的关键。以下是创建高复用组件的步骤:
1.1.1 创建按钮组件
在 src/components/
目录下创建 CustomButton.js
:
import React from 'react'; import { TouchableOpacity, Text, StyleSheet } from 'react-native'; const CustomButton = ({ title, onPress, style }) => { return ( <TouchableOpacity style={[styles.button, style]} onPress={onPress}> <Text style={styles.text}>{title}</Text> </TouchableOpacity> ); }; const styles = StyleSheet.create({ button: { backgroundColor: '#007bff', padding: 10, borderRadius: 5, alignItems: 'center', }, text: { color: '#fff', fontSize: 16, }, }); export default CustomButton;
1.1.2 使用自定义按钮
在页面中使用 CustomButton
:
import React from 'react'; import { View } from 'react-native'; import CustomButton from '../components/CustomButton'; const HomeScreen = () => { const handlePress = () => { console.log('Button Pressed'); }; return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <CustomButton title="Click Me" onPress={handlePress} /> </View> ); }; export default HomeScreen;
1.2 使用 PropTypes 和 TypeScript 检测类型
-
PropTypes:用于检测组件的属性类型。
-
TypeScript:提供静态类型检查,提高代码的可靠性和可维护性。
1.2.1 使用 PropTypes
-
安装 PropTypes:
npm install prop-types
-
在组件中使用 PropTypes:
import React from 'react'; import { TouchableOpacity, Text, StyleSheet } from 'react-native'; import PropTypes from 'prop-types'; const CustomButton = ({ title, onPress, style }) => { return ( <TouchableOpacity style={[styles.button, style]} onPress={onPress}> <Text style={styles.text}>{title}</Text> </TouchableOpacity> ); }; CustomButton.propTypes = { title: PropTypes.string.isRequired, onPress: PropTypes.func.isRequired, style: PropTypes.object, }; const styles = StyleSheet.create({ button: { backgroundColor: '#007bff', padding: 10, borderRadius: 5, alignItems: 'center', }, text: { color: '#fff', fontSize: 16, }, }); export default CustomButton;
1.2.2 使用 TypeScript
-
配置 TypeScript:
-
在项目根目录下创建
tsconfig.json
:{ "compilerOptions": { "allowJs": true, "esModuleInterop": true, "jsx": "react-native", "moduleResolution": "node", "strict": true } }
-
-
创建 TypeScript 组件:
在src/components/
目录下创建CustomButton.tsx
:import React from 'react'; import { TouchableOpacity, Text, StyleSheet, ViewStyle } from 'react-native'; interface CustomButtonProps { title: string; onPress: () => void; style?: ViewStyle; } const CustomButton: React.FC<CustomButtonProps> = ({ title, onPress, style }) => { return ( <TouchableOpacity style={[styles.button, style]} onPress={onPress}> <Text style={styles.text}>{title}</Text> </TouchableOpacity> ); }; const styles = StyleSheet.create({ button: { backgroundColor: '#007bff', padding: 10, borderRadius: 5, alignItems: 'center', }, text: { color: '#fff', fontSize: 16, }, }); export default CustomButton;
2. 动画
2.1 Animated API 的使用
React Native 提供了 Animated
API,用于实现简单的动画效果。
2.1.1 实现淡入动画
import React, { useRef, useEffect } from 'react'; import { Animated, Text, View, StyleSheet } from 'react-native'; const FadeInView = () => { const fadeAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(fadeAnim, { toValue: 1, duration: 2000, useNativeDriver: true, }).start(); }, [fadeAnim]); return ( <Animated.View style={{ ...styles.container, opacity: fadeAnim }}> <Text style={styles.text}>Fade In Animation</Text> </Animated.View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, text: { fontSize: 24, }, }); export default FadeInView;
2.2 React Native Reanimated
React Native Reanimated
是一个高性能的动画库,支持复杂的动画效果。
2.2.1 安装 Reanimated
npm install react-native-reanimated
2.2.2 实现缩放动画
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated'; const ScaleView = () => { const scale = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => { return { transform: [{ scale: scale.value }], }; }); const handlePress = () => { scale.value = withSpring(scale.value === 1 ? 1.5 : 1); }; return ( <View style={styles.container}> <Animated.View style={[styles.box, animatedStyle]}> <Text style={styles.text} onPress={handlePress}> Tap Me </Text> </Animated.View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, box: { width: 100, height: 100, backgroundColor: 'blue', justifyContent: 'center', alignItems: 'center', }, text: { color: '#fff', fontSize: 18, }, }); export default ScaleView;
2.3 手势与交互(React Native Gesture Handler)
React Native Gesture Handler
是一个用于处理手势交互的库。
2.3.1 安装 Gesture Handler
npm install react-native-gesture-handler
2.3.2 实现拖拽效果
import React from 'react'; import { View, StyleSheet } from 'react-native'; import { GestureHandlerRootView, PanGestureHandler } from 'react-native-gesture-handler'; import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated'; const DragView = () => { const translateX = useSharedValue(0); const translateY = useSharedValue(0); const animatedStyle = useAnimatedStyle(() => { return { transform: [ { translateX: translateX.value }, { translateY: translateY.value }, ], }; }); const onGestureEvent = Animated.event( [ { nativeEvent: { translationX: translateX, translationY: translateY, }, }, ], { useNativeDriver: true } ); return ( <GestureHandlerRootView style={styles.container}> <PanGestureHandler onGestureEvent={onGestureEvent}> <Animated.View style={[styles.box, animatedStyle]} /> </PanGestureHandler> </GestureHandlerRootView> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, box: { width: 100, height: 100, backgroundColor: 'red', }, }); export default DragView;
3. 性能优化
在 React Native 开发中,性能优化是提升用户体验的关键。以下是常见的性能优化技术和实践:
3.1 避免性能陷阱(渲染优化、PureComponent)
3.1.1 渲染优化
React Native 的渲染性能直接影响到应用的流畅度。以下是一些渲染优化的方法:
-
减少不必要的渲染:
-
使用
React.memo
或PureComponent
避免不必要的组件渲染。 -
避免在
render
方法中定义函数或对象,因为每次渲染都会创建新的引用。
-
-
使用
shouldComponentUpdate
:
在类组件中,可以通过shouldComponentUpdate
手动控制组件是否需要重新渲染。 -
使用
useMemo
和useCallback
:
在函数组件中,使用useMemo
缓存计算结果,使用useCallback
缓存函数引用。
3.1.2 PureComponent
PureComponent
是 React 提供的一个优化组件,它会自动对 props
和 state
进行浅比较,避免不必要的渲染。
-
示例:
import React, { PureComponent } from 'react'; import { View, Text } from 'react-native'; class MyComponent extends PureComponent { render() { console.log('MyComponent rendered'); return ( <View> <Text>{this.props.text}</Text> </View> ); } } export default MyComponent;
3.2 使用 Hermes 引擎
Hermes 是 Facebook 为 React Native 开发的高性能 JavaScript 引擎,能够显著提升应用的启动速度和运行性能。
3.2.1 启用 Hermes
-
Android:
在android/app/build.gradle
中启用 Hermes:project.ext.react = [ enableHermes: true ]
-
iOS:
在ios/Podfile
中启用 Hermes:use_react_native!( :hermes_enabled => true )
-
重新构建应用:
npx react-native run-android npx react-native run-ios
3.2.2 Hermes 的优势
-
更快的启动速度:Hermes 通过预编译 JavaScript 字节码减少启动时间。
-
更低的内存占用:Hermes 优化了内存管理,减少了内存使用量。
-
更好的调试支持:Hermes 支持 Chrome DevTools 和 Flipper 调试工具。
3.3 图片和资源的优化
图片和资源是影响应用性能的重要因素。以下是一些优化方法:
3.3.1 使用合适的图片格式
-
PNG:适合需要透明度的图片。
-
JPEG:适合不需要透明度的图片,文件体积较小。
-
WebP:Google 推出的图片格式,支持透明度和高质量压缩。
3.3.2 图片懒加载
使用 react-native-fast-image
库实现图片懒加载:
-
安装库:
npm install react-native-fast-image
-
使用示例:
import React from 'react'; import FastImage from 'react-native-fast-image'; const MyImage = () => { return ( <FastImage style={{ width: 200, height: 200 }} source={{ uri: 'https://example.com/image.jpg', priority: FastImage.priority.normal, }} resizeMode={FastImage.resizeMode.contain} /> ); }; export default MyImage;
3.3.3 资源压缩
-
使用工具(如 ImageOptim)压缩图片资源。
-
使用
react-native-svg
渲染矢量图,减少图片资源的使用。
4. 原生模块
4.1 自定义原生模块
原生模块允许开发者使用原生代码(Java/Kotlin 或 Objective-C/Swift)扩展 React Native 的功能。
4.1.1 创建原生模块(Android)
-
创建 Java 类:
在android/app/src/main/java/com/yourapp/
目录下创建CustomModule.java
:package com.yourapp; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; public class CustomModule extends ReactContextBaseJavaModule { CustomModule(ReactApplicationContext context) { super(context); } @Override public String getName() { return "CustomModule"; } @ReactMethod public void showMessage(String message) { android.util.Log.d("CustomModule", message); } }
-
注册模块:
在android/app/src/main/java/com/yourapp/
目录下创建CustomPackage.java
:package com.yourapp; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class CustomPackage implements ReactPackage { @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new CustomModule(reactContext)); return modules; } @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); } }
-
在
MainApplication.java
中注册包:@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new CustomPackage() // 添加自定义包 ); }
4.1.2 在 JavaScript 中调用原生模块
import { NativeModules } from 'react-native'; const { CustomModule } = NativeModules; CustomModule.showMessage('Hello from JavaScript!');
4.2 原生模块与 React Native 交互
原生模块可以与 JavaScript 代码进行双向通信,传递数据和调用方法。
4.2.1 传递数据
-
从 JavaScript 传递数据到原生模块:
通过@ReactMethod
注解的方法接收参数。 -
从原生模块传递数据到 JavaScript:
使用Promise
或Callback
返回数据。
4.2.2 使用 Promise 返回数据
-
修改原生模块:
@ReactMethod public void getDeviceInfo(Promise promise) { try { String deviceName = android.os.Build.MODEL; promise.resolve(deviceName); } catch (Exception e) { promise.reject("ERROR", e); } }
-
在 JavaScript 中调用:
CustomModule.getDeviceInfo() .then((deviceName) => console.log(deviceName)) .catch((error) => console.error(error));
4.3 使用 Native Modules 和 Native UI Components
-
Native Modules:用于扩展 JavaScript 的功能。
-
Native UI Components:用于创建自定义的原生 UI 组件。
4.3.1 创建 Native UI 组件(Android)
-
创建 ViewManager:
在android/app/src/main/java/com/yourapp/
目录下创建CustomViewManager.java
:package com.yourapp; import android.view.View; import com.facebook.react.uimanager.SimpleViewManager; import com.facebook.react.uimanager.ThemedReactContext; public class CustomViewManager extends SimpleViewManager<View> { @Override public String getName() { return "CustomView"; } @Override protected View createViewInstance(ThemedReactContext reactContext) { View view = new View(reactContext); view.setBackgroundColor(0xFF0000FF); // 设置背景颜色 return view; } }
-
注册 ViewManager:
在CustomPackage.java
中注册:@Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { return Arrays.<ViewManager>asList( new CustomViewManager() ); }
-
在 JavaScript 中使用:
import { requireNativeComponent } from 'react-native'; const CustomView = requireNativeComponent('CustomView'); const App = () => { return <CustomView style={{ width: 100, height: 100 }} />; }; export default App;
4.5 创建原生模块(iOS)
4.5.1 创建 Objective-C 类
-
打开 Xcode 项目:
在ios/
目录下打开.xcworkspace
文件。 -
创建 Objective-C 类:
-
在 Xcode 中,右键点击
YourApp
文件夹,选择New File
。 -
选择
Objective-C Class
,命名为CustomModule
。 -
确保类继承自
NSObject
。
-
-
编写代码:
在CustomModule.m
中编写以下代码:#import "CustomModule.h" #import <React/RCTLog.h> @implementation CustomModule RCT_EXPORT_MODULE(); RCT_EXPORT_METHOD(showMessage:(NSString *)message) { RCTLogInfo(@"Message from JavaScript: %@", message); } @end
-
RCT_EXPORT_MODULE()
:将类暴露给 React Native。 -
RCT_EXPORT_METHOD()
:将方法暴露给 JavaScript。
-
4.5.2 在 JavaScript 中调用原生模块
-
导入 NativeModules:
import { NativeModules } from 'react-native'; const { CustomModule } = NativeModules; CustomModule.showMessage('Hello from JavaScript!');
-
运行项目:
-
在 Xcode 中运行项目,查看控制台输出。
-
4.5.3 创建 Swift 原生模块
如果更喜欢使用 Swift,可以按照以下步骤创建原生模块。
4.5.3.1 创建 Swift 类
-
创建 Swift 文件:
-
在 Xcode 中,右键点击
YourApp
文件夹,选择New File
。 -
选择
Swift File
,命名为CustomModule.swift
。
-
-
编写代码:
在CustomModule.swift
中编写以下代码:import Foundation import React @objc(CustomModule) class CustomModule: NSObject { @objc func showMessage(_ message: String) { print("Message from JavaScript: \(message)") } }
-
创建桥接头文件:
-
如果项目中没有桥接头文件,Xcode 会提示创建。
-
在桥接头文件(
YourApp-Bridging-Header.h
)中添加以下代码:#import <React/RCTBridgeModule.h>
-
4.5.3.2 在 JavaScript 中调用 Swift 模块
-
导入 NativeModules:
import { NativeModules } from 'react-native'; const { CustomModule } = NativeModules; CustomModule.showMessage('Hello from Swift!');
-
运行项目:
-
在 Xcode 中运行项目,查看控制台输出。
-
4.6 原生模块与 React Native 交互
4.6.1 传递数据
-
从 JavaScript 传递数据到原生模块:
通过RCT_EXPORT_METHOD
或@objc
方法接收参数。 -
从原生模块传递数据到 JavaScript:
使用Promise
或Callback
返回数据。
4.6.2 使用 Promise 返回数据(iOS)
-
修改 Objective-C 模块:
在CustomModule.m
中添加以下代码:RCT_EXPORT_METHOD(getDeviceInfo:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject) { NSString *deviceName = [[UIDevice currentDevice] name]; if (deviceName) { resolve(deviceName); } else { reject(@"ERROR", @"Failed to get device name", nil); } }
-
在 JavaScript 中调用:
CustomModule.getDeviceInfo() .then((deviceName) => console.log(deviceName)) .catch((error) => console.error(error));
4.6.3 使用 Callback 返回数据(iOS)
-
修改 Objective-C 模块:
在CustomModule.m
中添加以下代码:RCT_EXPORT_METHOD(getDeviceInfoWithCallback:(RCTResponseSenderBlock)callback) { NSString *deviceName = [[UIDevice currentDevice] name]; callback(@[[NSNull null], deviceName]); }
-
在 JavaScript 中调用:
CustomModule.getDeviceInfoWithCallback((error, deviceName) => { if (error) { console.error(error); } else { console.log(deviceName); } });
4.7 使用 Native Modules 和 Native UI Components
4.7.1 创建 Native UI 组件(iOS)
-
创建 Objective-C 类:
-
在 Xcode 中,右键点击
YourApp
文件夹,选择New File
。 -
选择
Objective-C Class
,命名为CustomViewManager
。 -
确保类继承自
RCTViewManager
。
-
-
编写代码:
在CustomViewManager.m
中编写以下代码:#import "CustomViewManager.h" #import <React/RCTViewManager.h> #import <UIKit/UIKit.h> @interface CustomView : UIView @end @implementation CustomView - (instancetype)init { self = [super init]; if (self) { self.backgroundColor = [UIColor blueColor]; } return self; } @end @interface CustomViewManager : RCTViewManager @end @implementation CustomViewManager RCT_EXPORT_MODULE() - (UIView *)view { return [[CustomView alloc] init]; } @end
-
在 JavaScript 中使用:
import { requireNativeComponent } from 'react-native'; const CustomView = requireNativeComponent('CustomView'); const App = () => { return <CustomView style={{ width: 100, height: 100 }} />; }; export default App;
4.7.2 创建 Swift Native UI 组件
-
创建 Swift 类:
-
在 Xcode 中,右键点击
YourApp
文件夹,选择New File
。 -
选择
Swift File
,命名为CustomViewManager.swift
。
-
-
编写代码:
在CustomViewManager.swift
中编写以下代码:import Foundation import React @objc(CustomViewManager) class CustomViewManager: RCTViewManager { override func view() -> UIView! { return CustomView() } } class CustomView: UIView { override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = .blue } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
-
在桥接头文件中注册:
在YourApp-Bridging-Header.h
中添加以下代码:#import <React/RCTViewManager.h>
-
在 JavaScript 中使用:
import { requireNativeComponent } from 'react-native'; const CustomView = requireNativeComponent('CustomView'); const App = () => { return <CustomView style={{ width: 100, height: 100 }} />; }; export default App;
5. 实践环节
在实践环节中,学员将通过实际操作实现一个自定义下拉刷新组件,并使用 Reanimated 实现一个复杂的动画效果。
5.1 实现一个自定义下拉刷新组件
5.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init CustomRefreshApp
或
expo init CustomRefreshApp
-
安装依赖:
安装以下依赖:npm install react-native-gesture-handler react-native-reanimated
5.1.2 创建下拉刷新组件
在 src/components/
目录下创建 CustomRefreshControl.js
:
import React, { useRef, useState } from 'react'; import { View, Text, StyleSheet, Animated, ScrollView } from 'react-native'; import { PanGestureHandler, State } from 'react-native-gesture-handler'; const CustomRefreshControl = ({ onRefresh, children }) => { const translateY = useRef(new Animated.Value(0)).current; const [refreshing, setRefreshing] = useState(false); const onGestureEvent = Animated.event( [{ nativeEvent: { translationY: translateY } }], { useNativeDriver: true } ); const onHandlerStateChange = (event) => { if (event.nativeEvent.oldState === State.ACTIVE) { const offsetY = event.nativeEvent.translationY; if (offsetY > 100) { setRefreshing(true); Animated.timing(translateY, { toValue: 50, duration: 300, useNativeDriver: true, }).start(() => { onRefresh(() => { Animated.timing(translateY, { toValue: 0, duration: 300, useNativeDriver: true, }).start(() => setRefreshing(false)); }); }); } else { Animated.spring(translateY, { toValue: 0, useNativeDriver: true, }).start(); } } }; return ( <View style={styles.container}> <PanGestureHandler onGestureEvent={onGestureEvent} onHandlerStateChange={onHandlerStateChange} > <Animated.View style={{ transform: [{ translateY }] }}> <View style={styles.refreshContainer}> {refreshing ? ( <Text style={styles.text}>Refreshing...</Text> ) : ( <Text style={styles.text}>Pull down to refresh</Text> )} </View> <ScrollView>{children}</ScrollView> </Animated.View> </PanGestureHandler> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, }, refreshContainer: { height: 50, justifyContent: 'center', alignItems: 'center', backgroundColor: '#f5f5f5', }, text: { fontSize: 16, color: '#333', }, }); export default CustomRefreshControl;
5.1.3 在页面中使用下拉刷新组件
在 src/screens/
目录下创建 HomeScreen.js
:
import React, { useState } from 'react'; import { View, Text, StyleSheet } from 'react-native'; import CustomRefreshControl from '../components/CustomRefreshControl'; const HomeScreen = () => { const [data, setData] = useState(['Item 1', 'Item 2', 'Item 3']); const handleRefresh = (callback) => { setTimeout(() => { setData([...data, `Item ${data.length + 1}`]); callback(); }, 2000); }; return ( <CustomRefreshControl onRefresh={handleRefresh}> {data.map((item, index) => ( <View key={index} style={styles.item}> <Text style={styles.itemText}>{item}</Text> </View> ))} </CustomRefreshControl> ); }; const styles = StyleSheet.create({ item: { padding: 20, borderBottomWidth: 1, borderBottomColor: '#ccc', }, itemText: { fontSize: 18, }, }); export default HomeScreen;
5.1.4 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
5.1.5 运行效果
-
下拉页面时显示刷新提示。
-
松开后触发刷新操作,显示 "Refreshing..."。
-
刷新完成后,列表新增一项内容。
5.2 使用 Reanimated 实现一个复杂的动画效果
5.2.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init ComplexAnimationApp
或
expo init ComplexAnimationApp
-
安装依赖:
安装以下依赖:npm install react-native-reanimated react-native-gesture-handler
5.2.2 实现复杂动画
在 src/screens/
目录下创建 AnimationScreen.js
:
import React from 'react'; import { View, StyleSheet } from 'react-native'; import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, Easing, withRepeat, } from 'react-native-reanimated'; const AnimationScreen = () => { const scale = useSharedValue(1); const rotate = useSharedValue(0); const translateX = useSharedValue(0); const animatedStyle = useAnimatedStyle(() => { return { transform: [ { scale: scale.value }, { rotate: `${rotate.value}deg` }, { translateX: translateX.value }, ], }; }); const startAnimation = () => { scale.value = withRepeat(withSpring(1.5), -1, true); rotate.value = withRepeat(withTiming(360, { duration: 2000, easing: Easing.linear }), -1); translateX.value = withRepeat(withSpring(100, { damping: 2 }), -1, true); }; return ( <View style={styles.container}> <Animated.View style={[styles.box, animatedStyle]} onTouchStart={startAnimation} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, box: { width: 100, height: 100, backgroundColor: 'blue', }, }); export default AnimationScreen;
5.2.3 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
5.2.4 运行效果
-
点击蓝色方块后,方块会放大、旋转并水平移动。
-
动画会无限循环,直到再次点击方块停止。
评估标准
-
下拉刷新组件:
-
能够正确实现下拉刷新功能。
-
刷新时显示提示信息,刷新完成后更新列表。
-
-
复杂动画效果:
-
能够使用 Reanimated 实现复杂的动画效果。
-
动画流畅且可交互。
-
通过以上内容的学习,读者可以掌握自定义组件、动画、性能优化和原生模块开发等的核心技术,为开发高性能应用打下坚实基础。
第五部分:React Native 案例实战
学习目标
-
通过实战项目巩固所学知识,提升工程能力。
-
能够独立开发中小型 React Native 应用。
内容
-
小型案例
-
ToDo 应用
-
计时器
-
-
中型案例
-
电商应用(商品列表、购物车)
-
新闻类应用(API 数据加载与显示)
-
-
大型案例
-
即时聊天应用
-
视频播放和上传应用
-
实践环节
-
分组完成一个中型或大型项目,模拟真实开发流程。
-
使用 Git 进行版本控制,使用项目管理工具(如 Jira)分配任务。
学习目标
-
通过实战项目巩固所学知识,提升工程能力:
-
掌握 React Native 的核心技术和开发流程。
-
学会从需求分析到项目上线的完整开发流程。
-
-
能够独立开发中小型 React Native 应用:
-
掌握常见应用场景的开发方法(如 ToDo 应用、电商应用、新闻类应用)。
-
学会处理复杂业务逻辑和性能优化。
-
1. 小型案例
1.1 ToDo 应用
1.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init TodoApp
或
expo init TodoApp
-
安装依赖:
安装以下依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack
1.1.2 创建页面组件
在 src/screens/
目录下创建以下页面组件:
-
HomeScreen.js:
import React, { useState } from 'react'; import { View, Text, TextInput, Button, FlatList, StyleSheet } from 'react-native'; const HomeScreen = () => { const [task, setTask] = useState(''); const [tasks, setTasks] = useState([]); const addTask = () => { if (task.trim()) { setTasks([...tasks, { id: Math.random().toString(), text: task }]); setTask(''); } }; const removeTask = (id) => { setTasks(tasks.filter((task) => task.id !== id)); }; return ( <View style={styles.container}> <TextInput style={styles.input} placeholder="Enter a task" value={task} onChangeText={setTask} /> <Button title="Add Task" onPress={addTask} /> <FlatList data={tasks} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.taskItem}> <Text style={styles.taskText}>{item.text}</Text> <Button title="Remove" onPress={() => removeTask(item.id)} /> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, input: { borderWidth: 1, borderColor: '#ccc', padding: 10, marginBottom: 10, }, taskItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', }, taskText: { fontSize: 16, }, }); export default HomeScreen;
1.1.3 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
1.1.4 运行效果
-
输入任务并点击 "Add Task" 按钮,任务会添加到列表中。
-
点击 "Remove" 按钮,任务会从列表中移除。
1.2 计时器
1.2.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init TimerApp
或
expo init TimerApp
-
安装依赖:
安装以下依赖:npm install react-native-reanimated react-native-gesture-handler
1.2.2 创建计时器组件
在 src/screens/
目录下创建 TimerScreen.js
:
import React, { useState, useEffect } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; const TimerScreen = () => { const [time, setTime] = useState(0); const [isRunning, setIsRunning] = useState(false); useEffect(() => { let interval; if (isRunning) { interval = setInterval(() => { setTime((prevTime) => prevTime + 1); }, 1000); } return () => clearInterval(interval); }, [isRunning]); const startTimer = () => { setIsRunning(true); }; const stopTimer = () => { setIsRunning(false); }; const resetTimer = () => { setTime(0); setIsRunning(false); }; return ( <View style={styles.container}> <Text style={styles.timerText}>{time} seconds</Text> <View style={styles.buttonContainer}> <Button title={isRunning ? 'Pause' : 'Start'} onPress={isRunning ? stopTimer : startTimer} /> <Button title="Reset" onPress={resetTimer} /> </View> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, timerText: { fontSize: 48, marginBottom: 20, }, buttonContainer: { flexDirection: 'row', justifyContent: 'space-around', width: '60%', }, }); export default TimerScreen;
1.2.3 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
1.2.4 运行效果
-
点击 "Start" 按钮,计时器开始计时。
-
点击 "Pause" 按钮,计时器暂停。
-
点击 "Reset" 按钮,计时器重置为 0。
2. 中型案例
2.1 电商应用(商品列表、购物车)
2.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init ECommerceApp
或
expo init ECommerceApp
-
安装依赖:
安装以下依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack @react-navigation/bottom-tabs redux react-redux @reduxjs/toolkit
2.1.2 创建 Redux Store
在 src/store/
目录下创建 store.js
:
import { configureStore } from '@reduxjs/toolkit'; import cartReducer from './cartSlice'; const store = configureStore({ reducer: { cart: cartReducer, }, }); export default store;
2.1.3 创建 Slice
在 src/store/
目录下创建 cartSlice.js
:
import { createSlice } from '@reduxjs/toolkit'; const cartSlice = createSlice({ name: 'cart', initialState: { items: [], }, reducers: { addItem: (state, action) => { const existingItem = state.items.find((item) => item.id === action.payload.id); if (existingItem) { existingItem.quantity += 1; } else { state.items.push({ ...action.payload, quantity: 1 }); } }, removeItem: (state, action) => { state.items = state.items.filter((item) => item.id !== action.payload.id); }, }, }); export const { addItem, removeItem } = cartSlice.actions; export default cartSlice.reducer;
2.1.4 创建页面组件
-
HomeScreen.js:
import React from 'react'; import { View, Text, FlatList, Button, StyleSheet } from 'react-native'; import { useSelector, useDispatch } from 'react-redux'; import { addItem } from '../store/cartSlice'; const products = [ { id: '1', name: 'Product 1', price: 10 }, { id: '2', name: 'Product 2', price: 20 }, { id: '3', name: 'Product 3', price: 30 }, ]; const HomeScreen = () => { const dispatch = useDispatch(); return ( <View style={styles.container}> <FlatList data={products} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.productItem}> <Text style={styles.productText}>{item.name} - ${item.price}</Text> <Button title="Add to Cart" onPress={() => dispatch(addItem(item))} /> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, productItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', }, productText: { fontSize: 16, }, }); export default HomeScreen;
-
CartScreen.js:
import React from 'react'; import { View, Text, FlatList, Button, StyleSheet } from 'react-native'; import { useSelector, useDispatch } from 'react-redux'; import { removeItem } from '../store/cartSlice'; const CartScreen = () => { const cartItems = useSelector((state) => state.cart.items); const dispatch = useDispatch(); return ( <View style={styles.container}> <FlatList data={cartItems} keyExtractor={(item) => item.id} renderItem={({ item }) => ( <View style={styles.cartItem}> <Text style={styles.cartText}> {item.name} - ${item.price} x {item.quantity} </Text> <Button title="Remove" onPress={() => dispatch(removeItem(item))} /> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, cartItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', padding: 10, borderBottomWidth: 1, borderBottomColor: '#ccc', }, cartText: { fontSize: 16, }, }); export default CartScreen;
2.1.5 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
2.1.6 运行效果
-
在首页点击 "Add to Cart" 按钮,商品会添加到购物车。
-
在购物车页面点击 "Remove" 按钮,商品会从购物车中移除。
2.2 新闻类应用(API 数据加载与显示)
2.2.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init NewsApp
或
expo init NewsApp
-
安装依赖:
安装以下依赖:npm install axios @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack
2.2.2 创建页面组件
在 src/screens/
目录下创建 NewsScreen.js
:
import React, { useEffect, useState } from 'react'; import { View, Text, FlatList, StyleSheet } from 'react-native'; import axios from 'axios'; const NewsScreen = () => { const [news, setNews] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchNews = async () => { try { const response = await axios.get( 'https://newsapi.org/v2/top-headlines?country=us&apiKey=YOUR_API_KEY' ); setNews(response.data.articles); } catch (error) { console.error(error); } finally { setLoading(false); } }; fetchNews(); }, []); if (loading) { return ( <View style={styles.container}> <Text>Loading...</Text> </View> ); } return ( <View style={styles.container}> <FlatList data={news} keyExtractor={(item) => item.url} renderItem={({ item }) => ( <View style={styles.newsItem}> <Text style={styles.newsTitle}>{item.title}</Text> <Text style={styles.newsDescription}>{item.description}</Text> </View> )} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, padding: 20, }, newsItem: { marginBottom: 20, }, newsTitle: { fontSize: 18, fontWeight: 'bold', }, newsDescription: { fontSize: 14, color: '#666', }, }); export default NewsScreen;
2.2.3 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
2.2.4 运行效果
-
页面加载时显示 "Loading..."。
-
加载完成后显示新闻列表,包括标题和描述。
评估标准
-
电商应用:
-
能够实现商品列表和购物车功能。
-
使用 Redux 管理购物车状态。
-
-
新闻类应用:
-
能够调用 API 并显示新闻列表。
-
处理加载状态和错误情况。
-
3. 大型案例
3.1 即时聊天应用
3.1.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init ChatApp
或
expo init ChatApp
-
安装依赖:
安装以下依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack firebase @react-native-async-storage/async-storage react-native-gifted-chat
3.1.2 配置 Firebase
-
创建 Firebase 项目:
-
访问 Firebase 控制台,创建一个新项目。
-
在项目中添加一个 Android 或 iOS 应用,并下载配置文件。
-
-
配置 Firebase:
-
将
google-services.json
(Android)或GoogleService-Info.plist
(iOS)放入项目目录。 -
在
android/build.gradle
和ios/Podfile
中配置 Firebase。
-
-
初始化 Firebase:
在src/firebase.js
中初始化 Firebase:import firebase from 'firebase/app'; import 'firebase/auth'; import 'firebase/firestore'; const firebaseConfig = { apiKey: 'YOUR_API_KEY', authDomain: 'YOUR_AUTH_DOMAIN', projectId: 'YOUR_PROJECT_ID', storageBucket: 'YOUR_STORAGE_BUCKET', messagingSenderId: 'YOUR_MESSAGING_SENDER_ID', appId: 'YOUR_APP_ID', }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); } export { firebase };
3.1.3 创建聊天页面
在 src/screens/
目录下创建 ChatScreen.js
:
import React, { useEffect, useState } from 'react'; import { GiftedChat } from 'react-native-gifted-chat'; import { firebase } from '../firebase'; const ChatScreen = ({ route }) => { const { userId } = route.params; const [messages, setMessages] = useState([]); useEffect(() => { const unsubscribe = firebase .firestore() .collection('chats') .orderBy('createdAt', 'desc') .onSnapshot((snapshot) => { const messages = snapshot.docs.map((doc) => ({ _id: doc.id, ...doc.data(), createdAt: doc.data().createdAt.toDate(), })); setMessages(messages); }); return () => unsubscribe(); }, []); const onSend = (newMessages = []) => { const message = newMessages[0]; firebase.firestore().collection('chats').add({ ...message, createdAt: firebase.firestore.FieldValue.serverTimestamp(), user: { _id: userId, name: 'User', }, }); }; return ( <GiftedChat messages={messages} onSend={(newMessages) => onSend(newMessages)} user={{ _id: userId, }} /> ); }; export default ChatScreen;
3.1.4 创建登录页面
在 src/screens/
目录下创建 LoginScreen.js
:
import React, { useState } from 'react'; import { View, TextInput, Button, StyleSheet } from 'react-native'; import { firebase } from '../firebase'; const LoginScreen = ({ navigation }) => { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const handleLogin = async () => { try { const { user } = await firebase.auth().signInWithEmailAndPassword(email, password); navigation.navigate('Chat', { userId: user.uid }); } catch (error) { console.error(error); } }; return ( <View style={styles.container}> <TextInput style={styles.input} placeholder="Email" value={email} onChangeText={setEmail} /> <TextInput style={styles.input} placeholder="Password" value={password} onChangeText={setPassword} secureTextEntry /> <Button title="Login" onPress={handleLogin} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', padding: 20, }, input: { borderWidth: 1, borderColor: '#ccc', padding: 10, marginBottom: 10, }, }); export default LoginScreen;
3.1.5 配置导航器
在 App.js
中配置 Stack Navigator:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import LoginScreen from './src/screens/LoginScreen'; import ChatScreen from './src/screens/ChatScreen'; const Stack = createStackNavigator(); const App = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Login" component={LoginScreen} /> <Stack.Screen name="Chat" component={ChatScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
3.1.6 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
3.1.7 运行效果
-
在登录页面输入邮箱和密码,点击 "Login" 按钮进入聊天页面。
-
在聊天页面发送消息,消息会实时显示并保存到 Firebase。
3.2 视频播放和上传应用
3.2.1 项目初始化
-
创建项目:
使用 React Native CLI 或 Expo 创建一个新项目:npx react-native init VideoApp
或
expo init VideoApp
-
安装依赖:
安装以下依赖:npm install @react-navigation/native react-native-screens react-native-safe-area-context @react-navigation/stack react-native-video react-native-image-picker firebase
3.2.2 配置 Firebase
-
创建 Firebase 项目:
-
访问 Firebase 控制台,创建一个新项目。
-
在项目中添加一个 Android 或 iOS 应用,并下载配置文件。
-
-
配置 Firebase:
-
将
google-services.json
(Android)或GoogleService-Info.plist
(iOS)放入项目目录。 -
在
android/build.gradle
和ios/Podfile
中配置 Firebase。
-
-
初始化 Firebase:
在src/firebase.js
中初始化 Firebase:import firebase from 'firebase/app'; import 'firebase/storage'; const firebaseConfig = { apiKey: 'YOUR_API_KEY', authDomain: 'YOUR_AUTH_DOMAIN', projectId: 'YOUR_PROJECT_ID', storageBucket: 'YOUR_STORAGE_BUCKET', messagingSenderId: 'YOUR_MESSAGING_SENDER_ID', appId: 'YOUR_APP_ID', }; if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); } export { firebase };
3.2.3 创建视频播放页面
在 src/screens/
目录下创建 VideoPlayerScreen.js
:
import React, { useState } from 'react'; import { View, Text, Button, StyleSheet } from 'react-native'; import Video from 'react-native-video'; import { launchImageLibrary } from 'react-native-image-picker'; import { firebase } from '../firebase'; const VideoPlayerScreen = () => { const [videoUri, setVideoUri] = useState(null); const pickVideo = () => { launchImageLibrary({ mediaType: 'video' }, (response) => { if (response.uri) { setVideoUri(response.uri); uploadVideo(response.uri); } }); }; const uploadVideo = async (uri) => { const response = await fetch(uri); const blob = await response.blob(); const ref = firebase.storage().ref().child(`videos/${new Date().toISOString()}`); await ref.put(blob); const url = await ref.getDownloadURL(); console.log('Video uploaded:', url); }; return ( <View style={styles.container}> {videoUri && ( <Video source={{ uri: videoUri }} style={styles.video} controls resizeMode="contain" /> )} <Button title="Pick Video" onPress={pickVideo} /> </View> ); }; const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, video: { width: 300, height: 200, }, }); export default VideoPlayerScreen;
3.2.4 配置导航器
在 App.js
中配置 Stack Navigator:
import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import VideoPlayerScreen from './src/screens/VideoPlayerScreen'; const Stack = createStackNavigator(); const App = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="VideoPlayer" component={VideoPlayerScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default App;
3.2.5 运行项目
-
启动 Metro Bundler:
npx react-native start
-
运行 Android 项目:
npx react-native run-android
-
运行 iOS 项目:
npx react-native run-ios
3.2.6 运行效果
-
点击 "Pick Video" 按钮,选择本地视频文件。
-
视频会播放并上传到 Firebase Storage。
评估标准
-
即时聊天应用:
-
能够实现用户登录和实时聊天功能。
-
使用 Firebase 存储和同步消息。
-
-
视频播放和上传应用:
-
能够选择本地视频并播放。
-
视频会上传到 Firebase Storage。
-
4. 实践环节
在实践环节中,学员将通过分组合作完成一个中型或大型项目,模拟真实开发流程。同时,学员将使用 Git 进行版本控制,并使用项目管理工具(如 Jira)分配任务。
4.1 分组完成一个中型或大型项目
4.1.1 项目选择
学员可以选择以下项目之一,或根据兴趣自定义项目:
-
电商应用:
-
功能:商品列表、商品详情、购物车、订单管理、用户登录。
-
技术栈:React Native、Redux、Firebase、React Navigation。
-
-
新闻类应用:
-
功能:新闻列表、新闻详情、分类筛选、用户评论。
-
技术栈:React Native、Axios、React Navigation、Firebase。
-
-
即时聊天应用:
-
功能:用户登录、实时聊天、消息通知。
-
技术栈:React Native、Firebase、React Navigation、Gifted Chat。
-
-
视频播放和上传应用:
-
功能:视频播放、视频上传、用户登录。
-
技术栈:React Native、Firebase、React Navigation、React Native Video。
-
4.1.2 分组与角色分配
-
分组:
-
每组 3-5 人,根据项目复杂度调整人数。
-
-
角色分配:
-
项目经理:负责任务分配、进度跟踪和沟通协调。
-
前端开发:负责页面开发和交互逻辑。
-
后端开发:负责 API 设计和数据管理(如 Firebase)。
-
测试工程师:负责功能测试和 Bug 修复。
-
UI 设计师:负责界面设计和用户体验优化。
-
4.1.3 开发流程
-
需求分析:
-
确定项目功能和用户需求。
-
编写需求文档和功能列表。
-
-
技术选型:
-
选择合适的技术栈(如 React Native、Firebase)。
-
确定项目架构和目录结构。
-
-
任务分配:
-
使用项目管理工具(如 Jira)分配任务。
-
每个任务应明确负责人、截止日期和优先级。
-
-
开发与测试:
-
按照任务分配进行开发和测试。
-
定期进行代码评审和功能测试。
-
-
部署与上线:
-
使用 Firebase 或其他平台部署应用。
-
进行最终测试并发布应用。
-
4.2 使用 Git 进行版本控制
4.2.1 创建 Git 仓库
-
初始化仓库:
在项目根目录下运行以下命令:git init
-
关联远程仓库:
在 GitHub 或 GitLab 上创建一个远程仓库,并关联本地仓库:git remote add origin <远程仓库地址>
4.2.2 分支管理
-
主分支:
-
main
或master
分支用于存放稳定版本的代码。
-
-
开发分支:
-
develop
分支用于日常开发。
-
-
功能分支:
-
每个功能或任务创建一个独立分支(如
feature/login
)。 -
开发完成后,合并到
develop
分支。
-
-
发布分支:
-
release
分支用于发布前的测试和修复。
-
4.2.3 常用 Git 命令
-
创建分支:
git checkout -b feature/login
-
提交代码:
git add . git commit -m "添加登录功能"
-
推送代码:
git push origin feature/login
-
合并分支:
git checkout develop git merge feature/login
-
拉取最新代码:
git pull origin develop
4.3 使用项目管理工具(如 Jira)分配任务
4.3.1 创建项目
-
登录 Jira:
访问 Jira,创建一个新项目。 -
选择模板:
选择适合的模板(如 Scrum 或 Kanban)。
4.3.2 创建任务
-
添加任务:
-
为每个功能或模块创建任务(如 "实现登录功能")。
-
每个任务应包含描述、优先级、负责人和截止日期。
-
-
分配任务:
-
将任务分配给对应的开发人员。
-
4.3.3 跟踪进度
-
更新任务状态:
-
开发人员完成任务后,更新任务状态(如 "进行中" -> "已完成")。
-
-
每日站会:
-
每天召开站会,讨论任务进展和遇到的问题。
-
-
看板视图:
-
使用看板视图直观展示任务状态和进度。
-
4.4 评估标准
-
项目完成度:
-
项目功能是否完整,是否符合需求文档。
-
-
代码质量:
-
代码结构是否清晰,是否符合编码规范。
-
-
团队协作:
-
是否有效使用 Git 和项目管理工具。
-
团队成员是否积极参与和沟通。
-
-
项目文档:
-
是否提供完整的需求文档、设计文档和测试报告。
-
通过以上小、中、大型等案例实战,读者可以掌握复杂应用的开发技术,能够独立开发功能丰富的 React Native 应用。
第六部分:未来趋势与学习建议
学习目标
-
了解 React Native 的最新趋势和扩展学习方向。
-
掌握持续学习和职业发展的方法。
内容
-
最新功能和趋势
-
Fabric 新架构
-
Turbo Modules
-
React Native 和 Flutter 的对比
-
React Native 和 UniApp 的对比
-
-
学习资源
-
官方文档
-
社区论坛
-
开源项目和实战案例
-
-
职业发展建议
-
如何准备 React Native 开发岗位的面试
-
构建个人技术博客或开源项目
-
推荐后续学习方向(如前端工程化、移动端性能优化)
-
学习目标
-
了解 React Native 的最新趋势和扩展学习方向:
-
掌握 React Native 的最新功能和技术趋势。
-
了解 React Native 与其他跨平台框架(如 Flutter)的对比。
-
-
掌握持续学习和职业发展的方法:
-
学会利用官方文档、社区论坛和开源项目提升技能。
-
掌握面试技巧和职业发展规划。
-
1. 最新功能和趋势
1.1 Fabric 新架构
-
简介:Fabric 是 React Native 的新架构,旨在提升性能和开发体验。
-
核心改进:
-
同步渲染:减少 JavaScript 和原生代码之间的通信延迟。
-
更快的启动速度:通过优化初始化流程提升应用启动速度。
-
更好的内存管理:减少内存泄漏和性能瓶颈。
-
-
学习建议:
-
关注 React Native 官方博客和 GitHub 仓库,了解 Fabric 的最新进展。
-
尝试在新项目中使用 Fabric 架构,体验其性能优势。
-
1.2 Turbo Modules
-
简介:Turbo Modules 是 React Native 的新模块系统,旨在提升原生模块的性能和可维护性。
-
核心改进:
-
懒加载:按需加载原生模块,减少启动时间。
-
类型安全:通过代码生成工具提升类型安全性。
-
更好的调试支持:支持更强大的调试工具。
-
-
学习建议:
-
学习如何使用 Turbo Modules 开发高性能的原生模块。
-
参考官方文档和示例代码,掌握 Turbo Modules 的最佳实践。
-
1.3 React Native 和 Flutter 的对比
React Native:
-
优点:基于 JavaScript,学习曲线低;社区活跃,生态丰富。
-
缺点:性能略低于 Flutter,部分功能依赖第三方库。
Flutter:
-
优点:高性能,UI 一致性高;自带丰富的组件库。
-
缺点:基于 Dart 语言,学习曲线较高;生态相对较小。
以下是 React Native 和 Flutter 的详细对比:
特性 | React Native | Flutter |
---|---|---|
开发语言 | JavaScript(或 TypeScript) | Dart |
UI 渲染方式 | 使用原生组件(通过桥接层与原生代码通信) | 自绘引擎(Skia),不依赖原生组件 |
性能 | 接近原生性能,但依赖桥接层,可能存在性能瓶颈 | 高性能,自绘引擎直接渲染,无桥接层 |
学习曲线 | 较低,适合有 JavaScript 和 React 经验的开发者 | 较高,需要学习 Dart 语言和 Flutter 的 Widget 系统 |
社区和生态 | 社区活跃,生态丰富,第三方库众多 | 社区增长迅速,生态逐渐完善,但相比 React Native 稍显不足 |
热更新支持 | 支持热更新(Expo 或 CodePush) | 不支持热更新,需依赖第三方解决方案 |
跨平台支持 | 支持 iOS 和 Android | 支持 iOS、Android、Web、桌面端(Windows、macOS、Linux) |
开发工具 | 使用 Metro Bundler,支持 Expo 工具链 | 使用 Flutter CLI,支持 Android Studio 和 VS Code |
UI 一致性 | 依赖原生组件,不同平台 UI 可能不一致 | 自绘引擎,UI 一致性高 |
适用场景 | 适合中小型应用,快速原型开发 | 适合高性能应用,复杂 UI 需求 |
1.4 React Native 与 Uniapp 的对比
React Native
-
优点:
-
基于 JavaScript,学习曲线低,适合前端开发者快速上手。
-
社区活跃,生态丰富,第三方库众多。
-
接近原生性能,适合中小型应用开发。
-
-
缺点:
-
依赖桥接层与原生代码通信,可能存在性能瓶颈。
-
不同平台 UI 可能不一致,需要额外适配。
-
Uniapp
-
优点:
-
基于 Vue.js,学习曲线低,适合有 Vue.js 经验的开发者。
-
支持多端统一开发(iOS、Android、Web、小程序)。
-
社区活跃,生态丰富,尤其在国内市场应用广泛。
-
-
缺点:
-
性能较低,依赖 WebView 渲染,复杂场景可能存在性能问题。
-
部分功能依赖插件,原生能力较弱。
-
以下是 React Native 和 Uniapp 的详细对比:
特性 | React Native | Uniapp |
---|---|---|
开发语言 | JavaScript(或 TypeScript) | Vue.js + JavaScript |
UI 渲染方式 | 使用原生组件(通过桥接层与原生代码通信) | 使用 WebView 渲染(部分组件通过原生渲染) |
性能 | 接近原生性能,但依赖桥接层,可能存在性能瓶颈 | 性能较低,依赖 WebView 渲染,复杂场景可能存在性能问题 |
学习曲线 | 较低,适合有 JavaScript 和 React 经验的开发者 | 较低,适合有 Vue.js 经验的开发者 |
社区和生态 | 社区活跃,生态丰富,第三方库众多 | 社区活跃,生态丰富,但主要集中在国内 |
热更新支持 | 支持热更新(Expo 或 CodePush) | 支持热更新(通过 HBuilderX 或插件) |
跨平台支持 | 支持 iOS 和 Android | 支持 iOS、Android、Web、小程序(微信、支付宝等) |
开发工具 | 使用 Metro Bundler,支持 Expo 工具链 | 使用 HBuilderX,支持 Vue.js 开发 |
UI 一致性 | 依赖原生组件,不同平台 UI 可能不一致 | 使用 WebView 渲染,UI 一致性较高 |
适用场景 | 适合中小型应用,快速原型开发 | 适合多端统一开发(尤其是小程序和 H5) |
对比总结
-
React Native:
-
适合需要接近原生性能的中小型应用。
-
学习曲线低,社区活跃,适合快速开发。
-
-
Flutter:
-
适合高性能应用和复杂 UI 需求。
-
学习曲线较高,但跨平台支持更广泛(包括 Web 和桌面端)。
-
-
Uniapp:
-
适合多端统一开发(尤其是小程序和 H5)。
-
学习曲线低,但性能较低,适合轻量级应用。
-
学习建议
-
根据项目需求选择合适的框架:
-
如果需要高性能和复杂 UI,选择 Flutter。
-
如果需要快速开发和跨平台支持,选择 React Native。
-
如果需要多端统一开发(尤其是小程序),选择 Uniapp。
-
-
学习多种框架,扩展技术栈,提升职业竞争力。
2. 学习资源
2.1 官方文档
-
React Native 官方文档:
-
内容:入门指南、API 文档、最佳实践。
-
Expo 官方文档:
-
内容:Expo 工具链的使用方法和示例代码。
2.2 社区论坛
-
React Native Community:
-
内容:开源项目、讨论区、问题解答。
-
Stack Overflow:
-
内容:开发者问答社区,解决技术问题。
2.3 开源项目和实战案例
-
Awesome React Native:
-
内容:React Native 相关的开源项目、工具和资源。
-
React Native Elements:
-
地址:GitHub - react-native-elements/react-native-elements: Cross-Platform React Native UI Toolkit
-
内容:UI 组件库,提供丰富的 UI 组件和示例代码。
-
3. 职业发展建议
3.1 如何准备 React Native 开发岗位的面试
-
基础知识:
-
掌握 JavaScript、React 和 React Native 的核心概念。
-
熟悉常见的算法和数据结构。
-
-
项目经验:
-
准备 2-3 个完整的 React Native 项目,展示开发能力和解决问题的能力。
-
在 GitHub 上维护开源项目,展示代码质量和协作能力。
-
-
面试技巧:
-
练习常见的面试题(如组件生命周期、状态管理、性能优化)。
-
模拟面试,提升表达能力和应变能力。
-
3.2 构建个人技术博客或开源项目
-
技术博客:
-
记录学习笔记、项目经验和解决方案。
-
分享技术文章,提升个人影响力。
-
-
开源项目:
-
参与开源社区,贡献代码和文档。
-
创建自己的开源项目,解决实际问题。
-
3.3 推荐后续学习方向
-
前端工程化:
-
学习 Webpack、Babel 等构建工具。
-
掌握模块化开发和代码分割技术。
-
-
移动端性能优化:
-
学习如何优化 React Native 应用的启动速度和内存占用。
-
掌握性能分析工具(如 Flipper、React DevTools)。
-
-
跨平台开发:
-
学习 Flutter、SwiftUI 等其他跨平台框架。
-
掌握原生开发技术(如 Java/Kotlin、Objective-C/Swift)。
-
通过以上内容,学员将掌握 React Native 的最新趋势和学习方法,能够持续提升技能并规划职业发展。
附录
React Native 的适配难点、疑点、兼容性问题及解决方案
-
跨平台样式差异
-
设备尺寸和屏幕适配
-
导航的兼容性问题
-
性能问题
-
原生模块的兼容性
-
网络请求和缓存问题
-
Debug 与错误处理
在 React Native 开发中,跨平台适配、性能优化和错误处理是常见的挑战。以下是常见问题及其解决方案的详细说明:
1. 跨平台样式差异
问题
iOS 和 Android 上的样式表现不一致,例如字体、阴影、边距等。
解决方案
-
使用 Platform 模块定制化样式:
-
通过
Platform.OS
判断当前平台,为不同平台设置不同的样式。 -
示例:
import { Platform, StyleSheet } from 'react-native'; const styles = StyleSheet.create({ text: { fontSize: 16, marginTop: Platform.OS === 'ios' ? 10 : 5, }, });
-
-
检查字体、阴影和默认边距差异:
-
使用平台特定的字体(如 iOS 的 San Francisco 和 Android 的 Roboto)。
-
使用
Platform.select
设置阴影样式:const styles = StyleSheet.create({ box: { ...Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, }, android: { elevation: 4, }, }), }, });
-
2. 设备尺寸和屏幕适配
问题
不同屏幕尺寸上界面布局不美观,元素可能错位或溢出。
解决方案
-
使用 Dimensions 获取屏幕大小:
-
通过
Dimensions.get('window')
获取屏幕宽度和高度,动态调整布局。 -
示例:
import { Dimensions, StyleSheet } from 'react-native'; const { width, height } = Dimensions.get('window'); const styles = StyleSheet.create({ container: { width: width * 0.8, // 占用屏幕宽度的 80% height: height * 0.5, // 占用屏幕高度的 50% }, });
-
-
使用 PixelRatio 处理像素密度:
-
通过
PixelRatio.get()
获取设备像素密度,调整图片和字体大小。 -
示例:
import { PixelRatio } from 'react-native'; const scale = PixelRatio.get(); const fontSize = 16 * scale; // 根据像素密度调整字体大小
-
-
使用 react-native-responsive-dimensions:
-
安装库:
npm install react-native-responsive-dimensions
-
使用百分比设置尺寸:
import { widthPercentageToDP as wp, heightPercentageToDP as hp } from 'react-native-responsive-dimensions'; const styles = StyleSheet.create({ box: { width: wp('80%'), // 占用屏幕宽度的 80% height: hp('50%'), // 占用屏幕高度的 50% }, });
-
3. 导航的兼容性问题
问题
React Navigation 在某些设备上可能不流畅,页面切换卡顿或动画不流畅。
解决方案
-
优化路由栈:
-
避免嵌套过多的路由栈,减少页面切换的复杂度。
-
使用
createNativeStackNavigator
替代createStackNavigator
,提升性能。
-
-
升级到最新版本的 React Navigation:
-
定期更新 React Navigation 和相关依赖,修复已知问题。
-
示例:
npm install @react-navigation/native@latest @react-navigation/stack@latest
-
4. 性能问题
问题
动画卡顿和慢加载,影响用户体验。
解决方案
-
使用 Reanimated 替代 Animated API:
-
Reanimated 提供更高效的动画实现,支持复杂动画场景。
-
示例:
import Animated, { useSharedValue, useAnimatedStyle, withSpring } from 'react-native-reanimated'; const scale = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => { return { transform: [{ scale: scale.value }], }; }); const handlePress = () => { scale.value = withSpring(1.5); };
-
-
开启 Hermes 引擎:
-
Hermes 是 React Native 的高性能 JavaScript 引擎,显著提升启动速度和运行性能。
-
在
android/app/build.gradle
中启用 Hermes:project.ext.react = [ enableHermes: true ]
-
5. 原生模块的兼容性
问题
第三方库在不同版本上表现异常,可能导致崩溃或功能失效。
解决方案
-
检查第三方库的文档并选择稳定版本:
-
使用
npm outdated
检查依赖版本,更新到稳定版本。 -
示例:
npm install react-native-device-info@latest
-
-
手动编写桥接代码替代:
-
如果第三方库不兼容,可以手动编写原生模块替代。
-
参考 React Native 官方文档编写原生模块。
-
6. 网络请求和缓存问题
问题
数据加载慢或缓存失效,影响用户体验。
解决方案
-
使用 react-query 或 swr 进行数据缓存:
-
安装库:
npm install react-query
-
示例:
import { useQuery } from 'react-query'; const fetchData = async () => { const response = await fetch('https://api.example.com/data'); return response.json(); }; const { data, isLoading } = useQuery('data', fetchData);
-
-
配置本地持久化存储:
-
使用
AsyncStorage
或MMKV
存储数据。 -
示例:
import AsyncStorage from '@react-native-async-storage/async-storage'; const storeData = async (key, value) => { try { await AsyncStorage.setItem(key, value); } catch (error) { console.error(error); } }; const getData = async (key) => { try { const value = await AsyncStorage.getItem(key); return value; } catch (error) { console.error(error); } };
-
7. Debug 与错误处理
问题
难以追踪复杂错误,调试效率低。
解决方案
-
启用调试工具(React DevTools、Flipper):
-
使用 React DevTools 调试组件状态和性能。
-
使用 Flipper 调试网络请求、日志和性能。
-
-
结合 Sentry 进行错误监控:
-
安装 Sentry:
npm install @sentry/react-native
-
初始化 Sentry:
import * as Sentry from '@sentry/react-native'; Sentry.init({ dsn: 'YOUR_SENTRY_DSN', });
-
通过以上解决方案,学员可以有效应对 React Native 开发中的常见问题,提升应用的质量和用户体验。
结语
亲爱的读者朋友们:
经过漫长的学习和实践,我们已经一起完成了《React Native开发实战系统化学习》的旅程。从最基础的环境搭建、组件开发,到复杂的状态管理、性能优化,再到实战项目的开发与部署,我们一步步深入探索了 React Native 的方方面面。希望通过这本书,你们不仅掌握了 React Native 的核心技术,还培养了解决实际问题的能力。
React Native 作为一款强大的跨平台开发框架,为开发者提供了高效、灵活的解决方案。无论是中小型应用的快速开发,还是大型项目的复杂需求,React Native 都能胜任。然而,技术的学习永无止境,React Native 的生态也在不断演进。未来的 Fabric 新架构、Turbo Modules 等新技术将进一步提升开发体验和应用性能。希望你们能够持续关注 React Native 的最新动态,不断学习和实践。
在学习和开发的过程中,难免会遇到各种问题和挑战。但请记住,每一个问题的解决都是一次成长的机会。无论是跨平台适配的难点,还是性能优化的瓶颈,都可以通过查阅文档、参与社区讨论、阅读源码等方式找到解决方案。同时,也希望大家能够积极参与开源社区,分享自己的经验和成果,为 React Native 的生态贡献力量。
最后,感谢你们选择了这本书,并坚持完成了整个学习过程。希望这本书能够成为你们 React Native 开发路上的得力助手,也希望你们在未来的开发工作中能够不断突破自我,创造出更多优秀的应用。
祝愿大家在 React Native 的世界里,写出精彩的代码,实现自己的梦想!
致谢
感谢所有支持本书的读者、朋友和家人。特别感谢技术社区和开源贡献者,正是你们的无私奉献,才让 React Native 的生态如此繁荣。
联系我们
如果你对本书有任何建议或问题,欢迎通过以下方式联系我们:
-
邮箱:qq695926920@163.com
-
论坛:请直接在本博文下方评论区进行评论、建议或提问,感谢读者朋友们!
Happy Coding!
愿你们的每一行代码都充满创造力与乐趣!