文档传送门:
RN:reactnative.dev/docs/enviro...
Expo:docs.expo.dev/tutorial/in...
环境搭建
环境要求
- Node.js 和 npm:React Native 是基于 Node.js 平台的,需要先安装 Node.js 和 npm。可以在 Node.js 官网上下载并安装。
- Java Development Kit (JDK):React Native 需要使用 JDK 来编译 Java 代码。可以在 Oracle 官网上下载并安装最新版本的 JDK。
- Android Studio:如果你要在 Android 平台上开发 React Native 应用,那么需要安装 Android Studio。可以在 Android Studio 官网上下载并安装最新版本的 Android Studio。
- Xcode:如果要在 iOS 平台上开发 React Native 应用,那么需要安装 Xcode。可以在 App Store 上下载并安装最新版本的 Xcode。
React Native CLI Quickstart
翻开官网文档,你会发现搭建环境有两个 Quickstart 选项,一个是 React Native CLI Quickstart,这个是使用 RN 自己的命令行工具来初始化 RN 应用,用此方法时,如果你没有 macOS 系统,不借助第三方软件下你是无法构建 iOS App 的,这是硬件的限制。此外还需要安装各种各样的包,安装的过程非常非常的折腾。。。
Expo
使用 Expo 搭建 React Native 项目可以使开发者更快速地开始开发和测试,因为它提供了一些方便的工具和服务,如自动构建和打包、调试工具和可共享的应用程序。
以下是使用 Expo 搭建 React Native 项目的步骤:
- 安装 Expo CLI:
在命令行中运行以下命令以全局安装 Expo CLI:
npm install -g expo-cli
- 创建 Expo 项目:
在命令行中进入你想要创建项目的目录,并运行以下命令:
lua
npx create-expo-app AwesomeProject
其中,myProjectName 是你想要创建的项目名称。
- 启动 Expo 项目:
在命令行中进入项目目录,并运行以下命令:
bash
cd AwesomeProject
npx expo start
这将启动 Expo DevTools,展示运行的项目信息和一些方便的开发工具。在 Expo DevTools 中,你可以运行应用程序在你的 iOS 或 Android 设备上进行测试,或在你的电脑上使用模拟器。
- 编辑和修改项目:
打开你喜欢的编辑器(如 VS Code),在编辑器中打开项目文件夹,开始编辑和修改项目代码。React Native 项目的代码位于项目目录下的 App.js
文件中。
调试 RN
快捷键
- Ctrl + D:在运行 React Native 应用程序的模拟器或设备上,按下 Ctrl + D 可以打开调试菜单。在调试菜单中,你可以选择 Reload(重新加载)应用程序、显示控制台、显示网络请求等选项。
- Ctrl + M:打开调试菜单
- Ctrl + R:重新加载应用程序
- Ctrl + M + R: 强制重新加载应用程序并清除缓存。
- Ctrl + M + D: 打开远程调试菜单,并允许你使用 Chrome 开发者工具或 React Native Debugger 来调试应用程序。
调试工具
- React Native Debugger:React Native Debugger 是一种针对 React Native 应用程序的独立调试工具。它包含一个类似于 Chrome 开发者工具的界面,可以让你检查网络请求、查看控制台日志、检查 Redux 状态和运行 JavaScript 代码。React Native Debugger 还支持设置断点和单步调试代码。你可以在 github.com/jhen0409/re... 上找到 React Native Debugger 的下载链接和使用说明。注意 React Native Debugger 是针对 Chrome 设计的, 需要使用 chrome 内核的浏览器
- Chrome 开发者工具:你可以使用 Chrome 开发者工具来调试 React Native 应用程序中的 JavaScript 代码。首先,在运行应用程序的模拟器或设备上打开 Chrome 浏览器,并访问
chrome://inspect
。然后,你应该能够看到一个列表,其中包含你正在运行的应用程序。单击应用程序名称旁边的"inspect"按钮,即可打开 Chrome 开发者工具并开始调试应用程序。
React Native Debugger
- 打开 rn-debugger
- 更改端口号,在 .rndebuggerrc 中将 defaultRNPackagerPorts 改为终端中的端口号,保持一致
- 在完成更改后,保存并关闭
.rndebuggerrc
文件,重启 React Native Debugger
构建部署
app.json
在 app.json 中,可以配置 App 相关信息
expo.name:App 名称。
expo.slug:发布后的 URL。e.g.expo.dev/@project-owner/myAppName project
expo.assetBundlePatterns:需要打包进 App 的静态资源目录。
expo.updates.fallbackToCacheTimeout:更新策略配置。
expo.splash:配置加载屏。
Expo publish 和 Expo EAS 都可以用于部署和分享Expo应用程序,但它们的主要目的和功能不同。Expo publish主要用于快速部署和分享应用程序,而EAS则主要用于自动化构建和提交应用程序,以及更高效地管理开发流程。
Expo publish
Expo publish是Expo平台提供的一项功能,用于将Expo应用程序发布到Expo服务器上,并将其分享给其他人。发布应用程序后,其他人可以使用Expo Client应用程序或扫描QR码在其设备上运行你的应用程序。
使用:
-
在终端中运行以下命令,以将应用程序发布到Expo服务器上:
expo publish
如果这是你第一次发布应用程序,Expo将提示你输入一个新的应用程序版本号。你可以输入任何版本号,只要它比先前发布的版本号高即可。
- Expo将开始构建你的应用程序,并将其发布到Expo服务器上。这可能需要几分钟时间,具体取决于你的应用程序大小和网络连接速度。
- 发布完成后,Expo会向你提供一个URL和QR码,以便其他人可以轻松地找到和访问你的应用程序。你还可以在Expo网站上查看和管理你的应用程序版本历史记录。
注意,Expo publish只能用于发布JavaScript版本的Expo应用程序,如果你需要构建原生代码版本,则需要使用Expo EAS Build。
EAS
EAS(Expo Application Services)是Expo平台的一部分,它提供了一组工具和服务来帮助开发人员更轻松地构建和部署Expo应用程序。EAS的主要功能包括:
- EAS Build:一种构建服务,可以为Expo应用程序生成Android和iOS二进制文件,以便轻松部署到应用商店。
- EAS Submit:一种提交服务,可以将应用程序二进制文件自动提交到Google Play和Apple App Store。
- EAS CLI:一种命令行工具,可用于配置和管理EAS构建和提交服务。
- EAS Analytics:一种分析服务,可用于跟踪应用程序的使用情况和性能,并生成可视化报告。
使用:
- 配置EAS:在终端中运行以下命令来配置EAS构建服务:
bash
cd my-project
expo login
expo eas:init
这将使用你的Expo帐户凭据,将你的项目与EAS构建服务关联。
- 构建应用程序:在终端中运行以下命令来使用EAS构建服务为你的应用程序生成Android和iOS二进制文件:
less
expo eas:build --platform all
这将使用EAS构建服务为你的应用程序生成Android和iOS二进制文件。你可以在Expo Devtools网站上跟踪构建进度并下载生成的二进制文件。
-
提交应用程序:在终端中运行以下命令来使用EAS提交服务将你的应用程序自动提交到Google Play和Apple App Store:
expo eas:submit
这将使用EAS提交服务自动将你的应用程序二进制文件提交到Google Play和Apple App Store。你可以在Expo Devtools网站上跟踪提交进度并查看提交历史记录。
Expo
目前为止的学习过程中,我们大多还是依赖 RN 本身提供的能力,使用方法与 Web 开发时区别不是很大。而使用原生模块则不然,可能还需要修改安卓项目或 iOS 项目的配置,对刚刚入门的我们可能门槛还太高。这时使用 Expo 工作流的优势就显示出来了,Expo 大大降低了安装和使用原生模块的门槛。
选择图片
选择图片通过 expo-ImagePicker 来实现,首先安装依赖(注意使用的是 expo install)
arduino
expo install expo-image-picker
安装完成后,在文件中引入模块
javascript
import * as ImagePicker from 'expo-image-picker';
首先获取权限。没有权限但调用方法时,安卓会弹出授权框让用户确认,而 iOS 不会,需要手动调用授权功能让用户确认。
scss
// ...
const [status, requestPermission] = ImagePicker.useCameraPermissions();
const pickImage = async () => {
// status.granted 为当前是否有相机权限
if (!status.granted) {
// 没有权限就要请求权限
await requestPermission();
}
};
// ...
获取权限后,启动相机
ini
const result = await ImagePicker.launchCameraAsync();
有两点需要注意
第一:iOS 模拟器是无法打开相机的,调用不会有任何反应,而安卓模拟器会打开个模拟相机来拍摄。
第二:ImagePicker.launchCameraAsync
方法返回的的图像地址是临时的。
除了通过相机拍照获取图片,还可以通过相册来选择图片
php
// ImagePicker.launchImageLibraryAsync 方法还可以接收一个对象,来配置选中的图片
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
存储图片到本地
ImagePicker.launchCameraAsync 方法返回的的图像地址是临时的,如果需要保存到本地,需要使用 FileSystem 模块帮忙。
安装 expo-file-system 库来使用 FileSystem 模块
perl
expo install expo-file-system
引入模块
javascript
import * as FileSystem from 'expo-file-system';
每个 App 只允许在指定的文件夹下写入文件,通过一下属性获取该文件夹 uri
arduino
// 获取 App 可写的文件夹 uri,以 file:// 开头
console.log(FileSystem.documentDirectory);
通过"剪切"文件,将临时图片移动到 App 存储文件夹中
css
FileSystem.moveAsync({
from: 'file://xxx1',
to: 'file://xxx2'
})
更完整的存储系统
除了 FileSystem 模块,还可以使用 expo-sqlite 包来创建并使用本地数据库。
安装
expo install expo-sqlite
示例
javascript
// 引入模块
import * as SQLite from "expo-sqlite";
// 打开/创建数据库
// 数据库地址 {name}
const db = SQLite.openDatabase("rn-demo");
// 初始化数据库
export const initDB = () => {
return new Promise((res, rej) => {
// 执行事务
db.transaction((tx) => {
// 执行sql
tx.executeSql(
CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY NOT NULL, name VARCHAR),
[],
() => res(),
(_, err) => rej(err)
);
});
});
};
// 增加用户
export const insertUser = () => {
return new Promise((res, rej) => {
db.transaction((tx) => {
tx.executeSql(
INSERT INTO users (name) VALUES (?),
["lyf"],
(_, ret) => {
res(ret);
},
(_, err) => {
rej(err);
}
);
});
});
};
// 获取用户列表
export const getUser = () => {
return new Promise((res, rej) => {
db.transaction((tx) => {
tx.executeSql(
SELECT * FROM users,
[],
(_, ret) => {
res(ret);
},
(_, err) => {
rej(err);
}
);
});
});
};
位置功能与地图
位置功能使用 expo-location 包来实现,同样首先安装包
expo install expo-location 获取用户位置信息
javascript
// 引入模块
import * as Location from "expo-location";
const handleGetCurrentLocationBtnClick = async () => {
// 请求位置权限
let { status } = await Location.requestForegroundPermissionsAsync();
if (status !== "granted") {
setErrorMsg("获取位置权限被拒绝!");
return;
}
// 获取设备当前位置信息
let location = await Location.getCurrentPositionAsync({});
console.log(location);
};
地图展示需要使用一个叫 react-native-maps 的包,也是先安装包(注意这个不用 expo install 了)
css
npm i react-native-maps
使用示意
arduino
import React from "react";
// 还记得 RN 中这些组件都有什么用吗?
import { View, Text, StyleSheet, Button, Dimensions } from "react-native";
// 引入组件
import MapView from "react-native-maps";
const MapViewContainer = (props) => {
return (
<View>
<MapView
style={styles.map}
// 初始定位
initialRegion={{
// 经纬度值,可以通过
// 获取设备位置信息(Location.getCurrentPositionAsync)
// 的返回值 location.coords 中获得
latitude: 37.78825, // location.coords.latitude
longitude: -122.4324, // location.coords.longitude
// 下列两个属性是经纬度缩放比例
latitudeDelta: 0.0922,
longitudeDelta: 0.0421,
}}
/>
</View>
);
};
const styles = StyleSheet.create({
map: {
width: Dimensions.get("window").width,
height: 300,
},
});
export default MapViewContainer;
其他
键盘
如何关闭键盘?点击输入框可以弹出键盘,但是如果我们不提交的话,是无法手动关闭键盘的。如果需要关闭键盘,可以通过全局的 Touchable 组件,配合 KeyBoard API 来实现。
xml
<TouchableWithoutFeedback onPress={Keyboard.dismiss()}>
// ...
</TouchableWithoutFeedback>
屏幕
javascript
import {
useWindowDimensions,
Dimensions,
SafeAreaView
} from 'react-native';
// 1
// 获取设备像素信息
// 这里的 height width 是响应式的,会随着屏幕尺寸改变而改变
const { height, width } = useWindowDimensions();
// 2
// 监听屏幕方向变化
Dimensions.addEventListener("change", ({ window, screen }) => {})
// 3
// SafeAreaView 组件提供通用的安全显示区域,防止刘海屏遮挡屏幕内容
const App = () => {
return (
<SafeAreaView style={styles.container}>
<Text>内容</Text>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
}
});
// 4
// KeyboardAvoidingView
// 可以防止软键盘遮挡输入区
const KeyboardAvoidingComponent = () => {
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View>
<Text>Header</Text>
<TextInput placeholder="Username" />
<View>
<Button title="Submit" onPress={() => null} />
</View>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
};
检测平台
通过 Platform API 可以获取设备的平台信息
php
import { Platform, StyleSheet } from 'react-native';
// 获取当前操作系统名称
console.log(Platform.OS); // enum('android', 'ios')
// 使用 .select() 方法来获取类似 switch 的功能
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
android: {
backgroundColor: 'green'
},
ios: {
backgroundColor: 'red'
},
default: {
// other platforms, web for example
backgroundColor: 'blue'
}
})
}
});
另外 RN 提供了 Platform-specific extensions 的特性,帮助我针对不同平台进行个性化定制。当文件后缀.ios. 或 .android.,引入该文件时 RN 会自动根据不同平台加载不同代码。
对于以下两个文件
BigButton.ios.js
BigButton.android.js
RN 会自动根据平台引入对应的文件
javascript
import BigButton from './BigButton';
旋转
expo 初始化的项目根目录,会有 app.json 文件,其中的 expo.orientation 属性可以锁定 App 的旋转
json
{
"expo": {
// ...
// 一共有三种取值 default, portrait, landscape
// 默认为 default, 不限制转向
// portrait 时,限制程序为纵向
// landscape 时,限制程序为横向
"orientation": "portrait",
// ...
}
}
如果需要运行时更改屏幕的方向,可以使用 expo-screen-orientation 这个库来实现。