在构建我的 React Native 移动应用过程中学到的经验教训
谨慎选择第三方库
尽可能避免使用原生扩展
支持用户界面主题
添加平板电脑支持
保持性能
打造完美的启动画面
不要使用 CodePush
我正在开发一款名为Inkdrop的 Markdown 笔记应用,最近发布了适用于 iOS 和 Android 的新版移动应用。它使用React Native构建,React Native 是一个使用 JavaScript 和 React 构建原生移动应用的框架。
我从这个项目中学到了很多关于如何使用 React Native 创建高质量移动应用程序的知识,我想在本文中分享我的技巧。
我希望这篇文章能对那些已经开发或正在开发 React Native 移动应用的人有所帮助。
以下是我们将要涵盖的内容概要。
-
谨慎选择第三方库
-
尽可能避免使用原生扩展。
-
支持用户界面主题
-
添加平板电脑支持
-
保持性能
-
打造完美的启动画面
-
不要使用 CodePush
谨慎选择第三方库
与 iOS 上的 UIKit 不同,React Native 在构建炫酷的 UI 或导航方面提供的功能并不多。因为它专注于使用 React 和 JavaScript 提供基本的 UI 渲染和设备 API 访问。所以,你需要做很多工作才能让它看起来像你想要的那样。说实话,如果没有使用 React Native 上那些优秀的模块,我根本不可能完成这个项目。接下来我会告诉你我的应用使用了哪些库。
导航
如上图所示,我的应用程序有一个侧边栏,可以通过从屏幕左边缘滑动或点击工具栏按钮来激活,它还包含堆叠屏幕和模态屏幕。
为了实现路由和导航,我的应用采用了react-navigation。您可以轻松实现灵活的路由和流畅的屏幕过渡。但请注意,它不提供模态屏幕。您应该使用react-native-modal,它提供了增强的、动画效果好且可自定义的 React Native 模态屏幕。
如果您不需要非常特殊的布线模式,我强烈建议您使用它们。如果您需要,请查看这篇很棒的文章。
丰富的跨平台 UI 组件
iOS 和 Android 的 UI 设计规范不同。要实现符合两个平台标准的按钮、表格和标题,既困难又耗时。虽然市面上有很多美观的第三方组件,但你需要在应用中安装大量模块,最终会导致应用臃肿不堪,并出现各种 bug。
NativeBase是一套适用于 React Native 的跨平台 UI 组件库,它解决了这个问题。它类似于 React Native 版的 Twitter Bootstrap。它不仅提供了一套设计精良的基础组件,还包含一些布局组件。您无需担心应用运行在哪个平台上,因为组件样式会自动切换。
尽可能避免使用原生扩展
由于 React Native 是一项前沿技术,其 API 经常变更,这往往会导致第三方库无法正常工作。如果问题出在原生端,解决起来将异常艰难。对于库的开发者来说,这始终是一个难题,因为:
我们发现,大多数 React Native 开源项目都是由只有一两个平台经验的人编写的——例如Airbnb。
他们并非都是所有平台的专家。我曾为 React Native 开发过一个SQLite3 原生插件,也发现维护这两个平台相当困难。
如果你决定安装带有原生桥接器的库,就必须记住这一点。我经常需要查看原生代码来调试问题,所以你需要一些 iOS 和 Android 方面的经验。避免使用这些原生桥接库可以减少这种麻烦。
以下是我的应用中使用的所有带有原生桥接功能的库:
-
react-native-wkwebview-reborn - iOS 版 WKWebView
-
react-native-image-picker - 它允许您使用原生 UI 从设备库或直接从摄像头选择媒体。
-
react-native-japanese-tokenizer(我自己制作的)- 日语分词器
-
react-native-sqlite-2(我自己写的)- SQLite3 桥接器
减少对原生扩展的依赖,可以使你的应用更容易维护,以便兼容未来的 React Native 版本。
支持用户界面主题
对于 React Native 应用来说,支持主题是一项挑战,因为这完全取决于视图的渲染方式。与 iOS UIKit 不同,React Native 不提供任何外观代理,因此你需要为 React Native 开发一个等效的外观代理。
幸运的是,NativeBase 支持主题化。您只需定义如下变量,即可轻松自定义 NativeBase 组件的外观:
const $defaultBgColor = '#2E3235'
const $defaultFgColor = 'rgba(255, 255, 255, 0.7)'
const nativeBaseTheme = {
toolbarBtnColor: $defaultFgColor,
toolbarBtnTextColor: $defaultFgColor,
toolbarDefaultBg: $defaultBgColor,
toolbarDefaultBorder: 'rgba(0, 0, 0, 0.3)',
}
<StyleProvider variables={nativeBaseTheme}>
<View>...</View>
</StyleProvider>
但这还不够,因为它不适用于非 NativeBase 组件。所以我使用了react-native-extended-stylesheet,它允许你在样式表中使用变量,如下所示:
// app entry: set global variables and calc styles
EStyleSheet.build({
$bgColor: '#0275d8'
});
// component: use global variables
const styles = EStyleSheet.create({
container: {
backgroundColor: '$bgColor'
}
});
<View style={styles.container}>
...
</View>
非常简单。现在您可以定义所有组件的外观了!
注意:需要重新启动才能应用新主题,因为NativeBase StyleProvider 会缓存样式,目前没有办法清除缓存。
添加平板电脑支持
如果您想为平板电脑制作双栏布局,这很简单:
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row'
},
leftViewContainer: {
flexShrink: 0,
flexGrow: 0,
width: 200
},
rightViewContainer: {
flex: 1
}
})
<View style={styles.container}>
<View style={styles.leftViewContainer}>
...
</View>
<View style={styles.rightViewContainer}>
...
</View>
</View>
然而,它需要一些技巧才能支持根据屏幕尺寸切换布局,因为存在一个问题,即它本身Dimensions 不支持此功能Dimensions.get。即使在 iPad 上使用“分屏浏览”或“侧拉”模式,应用始终显示相同的尺寸。
console.log(Dimensions.get('screen')) // {fontScale: 1, width: 768, height: 1024, scale: 2}
console.log(Dimensions.get('window')) // {fontScale: 1, width: 768, height: 1024, scale: 2}
所以你需要获取窗口的实际大小。为此,你需要创建一个位于最外层的视图,并为其设置样式flex: 1。然后设置onLayout事件来获取窗口大小,并将其存储在某个地方,例如 Redux store 中。
以下是我的代码片段:
保持性能
使用 PureComponents
随着应用程序的不断发展,您最终需要提升应用程序的性能。在 React Native 中,您可以参考以下许多 React 应用程序性能优化技巧:
保持应用运行速度的一个常见基本技巧是使用 `recompose`shouldComponentUpdate()来避免组件不必要的重复渲染。`recompose`React.PureComponent在这方面非常实用,因为它会在组件的 props 没有改变时自动跳过渲染。我个人更喜欢使用`recompose`来pure实现高阶组件 (HOC) 模式。
不要在 Render() 函数中创建回调函数
render()现在你有了 PureComponents,但如果你有一个像这样的方法,那就没有意义了:
function CommentList(props) {
return (
<div>
{props.comments.map((comment) => (
<Comment comment={comment} key={comment.id} onPress={() => props.handlePressCommentItem(comment)} />
))}
</div>
);
}
onPress因为每次渲染 `Comment` 组件时都会创建一个新的函数CommentList,所以 `Comment`(纯组件)会认为它的 props 总是会改变。因此,渲染评论列表会消耗大量资源,因为所有评论都会被重新渲染。为了避免这种情况,请不要创建回调函数:
function CommentList(props) {
return (
<div>
{props.comments.map((comment) => (
<Comment comment={comment} key={comment.id} onPress={props.handlePressCommentItem} />
))}
</div>
);
}
如果您的列表可能很长,强烈推荐使用FlatList 。
打造完美的启动画面
图。避免在 JS 加载时出现空白白屏。
如果你尝试在 React Native 中设置启动画面,那么你可能遇到过内容加载前屏幕闪过一圈白屏的情况。如果你的应用本身就是白色背景,这种情况通常不太明显,但仍然很烦人。
我推荐你阅读这篇文章,它详细介绍了如何为 iOS 和 Android 构建完美的启动画面。非常有帮助。
不要使用 CodePush
CodePush让您可以轻松地为应用添加动态更新体验。借助 CodePush,您无需每次都通过应用商店发布补丁版本,从而可以快速修复问题。
但我并不建议您使用它。首先,App Store 的审核时间现在非常短。截至撰写本文时,平均只需两天即可完成审核,这对于您的业务来说通常已经足够快了。其次,它会使您的应用变得复杂,因为 CodePush 库是一个原生模块。正如我上面提到的,为了保持应用的简洁性,您应该避免使用原生扩展。
希望这对您有所帮助!
感谢阅读本文!我是松山拓也,一名居住在日本东京的自由开发者。我正在努力独立打造一款盈利产品,并在博客上记录我的创业历程。欢迎访问我的博客!
文章来源:https://dev.to/craftzdog/lessons-learned-while-building-my-react-native-mobile-app-3080






