📢 上篇文章 是我在 2021 年左右发布的, 如今部分内容已经过时了, 恰逢年底, 正好在做一个开发 React Native(Expo 框架) 应用的总结.
技术选型
组件/功能
🔥 这里是笔者使用的在 React Naitve/JS/Expo 生态中最好的库/组件.名称 | 功能说明 | 备注 |
---|---|---|
docs.expo.dev/versions/la… | 获取用户设备本地化信息, 例如设备使用的语言, 设备使用的文字方向 | |
docs.expo.dev/versions/la… | 扫码/从图片中识别条形码 | |
docs.expo.dev/versions/la… | 读取和写入剪切板 | |
docs.expo.dev/versions/la… | 唤醒系统的分享 | |
docs.expo.dev/versions/la… | 对生物识别(指纹/FaceId/TouchID) 封装 | |
docs.expo.dev/versions/la… | 对文件系统的封装, 例如获取缓存位置, 写入本地文件, 读取本地文件… | 如果你不使用 Expo, 更推荐使用 github.com/itinance/re… |
docs.expo.dev/versions/la… | 图片选择器, 调用系统图片选择, 并且系统裁剪功能 | |
docs.expo.dev/versions/la… | 图库选择器, 和上面不同的是, 它还支持选择视频, 以及读取图库, 基于这个库你可以开发一个自定义的图库选择器 | |
docs.expo.dev/versions/la… | 实现 Intent 功能, 方便打开系统配置. | 当你想要开启 App 设置时很有用, 例如用户未授予 App 相机权限, 使用这个库可以直接跳转到 App 设置 |
docs.expo.dev/versions/la… | 实现创建通知/撤销通知/管理小红点(badge) 等通知相关的处理 | |
docs.expo.dev/versions/la… | 获取 App 的信息, 例如包名/版本号等信息 | |
docs.expo.dev/versions/la… | 打开系统浏览器 | 当你想要打开一个超链接, 但是不想调用系统浏览器时可以使用这个库, 调用后会在 App 里面直接打开网页, 不用跳转第三方浏览器. |
docs.expo.dev/versions/la… | 线性渐变实现 | |
github.com/dohooo/reac… | 走马灯/轮播 | |
github.com/fnando/i18n… | 实现 I18N | 笔者的架构有些复杂, 我更推荐 , 它可以更好的和 react 结合. |
docs.expo.dev/guides/icon… | 对 github.com/oblador/rea… 的封装, 提供更多友好的 api | |
github.com/tokkozhin/r… | 生成二维码, 提供更多样式支持. | |
github.com/mrousavy/re… | 提供持久化存储支持, 类似浏览器中的 LocalStorage | 另一个替代品, 性能没那么好 docs.expo.dev/versions/la… |
www.npmjs.com/package/rea… | Webview 支持, 同时还支持双向通信, 注入 JS 代码… | |
github.com/react-nativ… | 弹出层实现 | |
github.com/deanhet/rea… | 文字滚动/marquee/ticker | |
docs.expo.dev/tutorial/sc… | 将 React 节点绘制成图片, 相当于 React Native 的 html2canvas | |
docs.expo.dev/versions/la… | 获取设备的网络信息 | |
github.com/numandev1/r… | 提供图片/视频/音频的压缩 | 如果你有图片的需求, 请使用这个库, 而不是 expo-image-manipulator 因为 expo-image-manipulator 很差 |
基础组件
⚙ 这里列出由 React Native 社区精心维护, 为 React Native 查漏补缺, 完善 React Native 官方没有做好的基础功能的库/组件.名称 | 功能说明 | 备注 |
---|---|---|
github.com/wix-incubat… | 对于可滚动视图中, 弹出键盘的逻辑处理 | 更多细节: juejin.cn/post/710678… |
github.com/DylanVann/r… | 高性能的图片渲染组件, 可完美替代 RN 的 Image 组件 | 另一个替代品 docs.expo.dev/versions/la… |
github.com/margelo/rea… | 高性能的图表组件 | 依赖 github.com/Shopify/rea…, 只要你有图表需求, 并且对性能要求比较高, 请选择这个库. 注意 skia 会显著增加包大小. |
github.com/software-ma… | 实现 SVG 渲染 | 很多库都依赖它, 无脑安装. |
github.com/software-ma… | 高性能动画实现 | 很多库都依赖它, 无脑安装. |
github.com/software-ma… | 手势支持 | 很多库都依赖它, 无脑安装. |
Polyfill/垫片
🛠 这里是列出常见 Polyfill名称 | 功能说明 | 备注 |
---|---|---|
github.com/charpeni/re… | 提供 React Native URL 对象的实现 | |
github.com/browserify/… | 提供 Nodejs stream 模块实现 | |
github.com/sindresorhu… | 提供 Nodejs querystring 模块实现 |
Base64
在 RN 中, atob
和 btoa
是没有被引擎实现, 这就意味着开发者要自行实现或引入 Polyfill, 在 Google React Native base64 polyfill
后 最热门的 Stackoverflow 回答贴 是建议开发者使用 base64 作为 Polyfill, 实际上这不是一个好主意, 特别是当你要处理加密货币相关的逻辑时, 性能过于羸弱, 这里强烈建议使用 react-native-quick-base64 作为 Polyfill, 它由 C++
实现, 在我的测试中, 同一个函数, 使用 base64 要执行 ≈2000ms
而使用 react-native-quick-base64 时仅 ≈100ms
就能执行完成
Crypto
在 RN 中, global.crypto 是未实现的, 和 base64 一样, 它的 Polyfill 有很多(crypto-js, crypto-browserify), 如果对性能有要求, 请使用 react-native-quick-crypto
Buffer
在 RN 中, global.buffer 是未实现的, 和 base64 一样, 它的 Polyfill 有很多(buffer, safe-buffer), 如果对性能有要求, 请使用 react-native-buffer
应该自己实现组件
👉 在 App 开发中, 我们程序员(苦逼)往往要根据产品和 UI 完成最终样式, 这使得 App 不像传统的 Web 后台一样使用 Element/Antd 之类一把梭, 笔者也尝试使用 Navi Base/React Native Elements, 效果并不好, 所以还是要对基础组件进行具体的操作和样式封装, 这里笔者列出常见的组件的实现方法, 当然这部分主要面向于有开发经验的程序员, 如果你刚刚入门, 笔者建议使用 Navi Base/React Native Elements 组件库.底部弹出框/Action Sheet: 使用 react-native-modal + react-native-gesture-handler 封装
CheckBox/CheckBoxGroup: 参考 react-native-checkbox
LightBox/图片预览: 使用 react-native-modal + react-native-reanimated-carousel 封装
我弃用了哪些组件/库
名称 | 原因 | 替代品 |
---|---|---|
react-native-async-storage.github.io/async-stora… | 性能原因 | github.com/mrousavy/re… |
github.com/gorhom/reac… | 维护原因 | 使用 github.com/react-nativ… + github.com/software-ma… 封装 |
github.com/expo/react-… | 维护原因 | 使用 github.com/react-nativ… + github.com/software-ma… 封装 |
github.com/kcotias/rea… | 维护原因 | 使用 github.com/react-nativ… + github.com/software-ma… 封装 |
tvke.github.io/react-nativ… | 可读性差 | 使用传统 StyleSheet 代替 |
github.com/react-nativ… | 维护原因 | 自行封装 |
github.com/arnnis/reac… | 维护原因 | 自行封装 |
github.com/leecade/rea… | 性能和使用 | github.com/dohooo/reac… |
github.com/awesomejerr… | 性能和更多样式支持 | github.com/tokkozhin/r… |
node-libs-expo | 参考 polyfill 部分, 不在需要这个库 | |
github.com/indiespirit… | 性能原因, 当我在页面上渲染超过五个图表时, 设备发热和卡顿异常明显. | github.com/margelo/rea… |
Monorepo
monorepo 在之前的文章中已经总结过, 并且内容也没有过时, 请参考: 基于 Expo 的 App 开发小计
热更新
注意事项/坑
- 在
miui
的部分版本中, 文字可能无法完整显示, 这里推荐的做法是封装Text
组件, 然后指定一个默认字体.
import { Text, TextProps } from "react-native";
export function YourText(props: TextProps) {
return <Text
{...props}
allowFontScaling={false}
style={[props.style, {fontFamily: props.style.fontFamily || "roboto"}]}
/>
}
- 如果你在使用
firebase-messaging
和expo
时, 请注意在 Android 上通知图标可能是没有的, 这是因为如果你没有指定通知图标, Android 将使用你的应用图标作为通知图标, 但是大多数应用图标都不能作为通知图标(通知图标要求背景透明, 图标纯色), 更多细节可以看笔者为react-native-firebase
的 PR. - 在 Expo 49 SDK 中,
usesCleartextTraffic
由系统决定, 这个选项意味着应用程序是否可以访问http
资源, 开发者可以通过expo-build-propertites
配置.
[
"expo-build-properties",
{
android: {
// false 则不允许 http 资源
usesCleartextTraffic: false,
},
},
];
- iOS 应用的审核要求用户拒绝授予某项权限后为用户提供一个友好的跳转, 例如: 用户点击拍照后拒绝授权相机, 开发人员必须提示
用户未授权
的字眼, 并且提供指向设置
的按钮, 下面是一个简单的跳转到设置的实现.
import { Linking, Platform } from "react-native";
import * as IntentLauncher from "expo-intent-launcher";
import * as Application from "expo-application";
export namespace Camera {
export const goAppSetting = () => {
if (Platform.OS === 'ios') {
Linking.openURL(`app-settings:`);
} else {
const activityAction = IntentLauncher.ActivityAction.APPLICATION_DETAILS_SETTINGS;
const options = {
data: `package:${Application.applicationId}`,
};
IntentLauncher.startActivityAsync(activityAction, options);
}
}
}
@expo/vector-icons
不显示图标, 这个是一个相对冷门的问题, 在monorepo
中, 如果在 App 仓库外引用@expo/vector-icons
则会导致图标不显示, 解决方式时将所有涉及到@expo/vector-icons
的代码移动到 App 里面, 笔者的复现方式如下
Root
apps
app1 // App
shared
组件库 // 如果在这里引用 @expo/vector-icons 就会导致图标无法显示