如果你喜欢我的文章,希望点赞 收藏 评论 三连支持一下,谢谢你,这对我真的很重要!


React Native 开发时,如果只是写些简单的页面,基本上按着官方文档 reactnative.dev就能写出来,但是 React Native 的 API 有几百个,没有一定的开发踩坑经验,面对一些新的需求时确实会抓不到重点。

本文总结了我个人开发 React Native 中遇到的问题和一些冷门的 API,如果有有缘人看到这篇文章并解决了实际问题,那就最好不过了。

一、内置组件

本节内容主要是是对官网 React Native Core Components 内容的补充,主要是说一些让人开发体验不爽的地方,帮助后来人避坑。

1.View

View 组件作为最基础的组件,撑起了 RN 页面的半壁江山,在使用的过程中有几个属性比较冷门但个人认为挺有用的属性。

  • hitSlop 属性:这个属性可以扩大 View 的触控范围,在一些小按钮上用收益还是很大的
  • pointerEvents 属性:这个属性类似 CSS 的 pointer-events 属性,可以控制 View 对 touch 事件的响应

2.Text

Text 组件是很常用的属性,有几个小点需要开发者注意一下:

  • Android 上存在吞字现象,现象是部分机型上最后一个字符不显示,原因不明。目前的折衷方案是文字的最后一行多加一个空格 or 零宽字符
  • Android 有个属性叫 includeFontPadding,设置为 false 后可以减少文字上下的 padding(这个 padding 是为角标字符预留的,例如 H₂O、2ⁿᵈ),这样可以更好的实现上下垂直居中对齐
  • 实现文字的居中对齐时,最好用一个 View 嵌套一个 Text 标签,然后给 View 设置一些 flex 属性控制 Text 居中对齐。Web 开发中经常使用 lineheight 属性实现单行文字的垂直居中对齐,这种实现方式本来就是权宜之计,在 RN 上行不太通。最佳实践还是利用 flex 属性实现居中对齐
  • 字体的配置相对来说比较麻烦,有个不错的教程 Ultimate guide to use custom fonts in react native 可以参考一下

3.TextInput

输入框组件也是很常用的属性,个人用下来有几个不爽的地方:

  • iOS/Android 的默认样式差距比较大,不做封装的话会写非常多的平台相关代码

  • placeholder 的文字比较长时,若出现换行现象,没有 API 去控制它的行高

  • 若一个页面出现多个 TextInput 组件时,需要用 ScrollView 组件包裹,才能实现不同 TextInput 组件焦点切换的功能

4.Image

Image 组件在表现上我个人认为非常优秀了,但在一些细节上初步上手的同学可能还是不太习惯:

  • 没有 CSS 那么多的滤镜属性,只支持模糊效果,不过个人基本没遇到过图像滤镜需求
  • 加载网络图片时,必须指定图片宽高,若不设置尺寸默认为 0
  • Android 上图片尺寸非常大时(貌似是 5000px?),图片会直接加载不出来,不过这种场景很少很少,基本都会瓦片图分步加载,要不然大图会引起 OOM 的
  • iOS/Android 对 webp 的支持也不是开箱即用的,需要分别配置:

    • iOS 使用 SDImageWebPCoder 提供支持
    • Android 使用 fresco 提供支持
    • 具体配置方案可以参考 react-native-webp-format
  • Android 不支持点九图

5.Modal

RN 官方之前提供的 Modal 组件有个很明显的问题,Modal 无法覆盖到状态栏。比如说我们做了一个弹窗,背景是黑色半透明的,但状态栏是白色的,这样在感官上就非常的割裂。

所幸 0.62 版本上了一个 statusBarTranslucent 属性,设为 true 就可以覆盖到状态栏之上。如果是 0.62 以下的版本,就需要改一些配置了,可以参考 stackoverflow 的这个回答:How to hide the statusBar when react-native modal shown?

6.ScrollView

ScrollView 组件是 RN 提供的滑动容器组件,有几个比较冷门但是很好用的 API 我这里说明一下。

第一个是吸顶功能,涉及到 StickyHeaderComponentstickyHeaderIndices 这两个 API,可以实现滚动吸顶的效果,非常的好用。

第二个是 automaticallyAdjustContentInsets 属性,有时候 iOS 滚动列表上会出现莫名其妙的空白区域,这个是 iOS Native 层实现的,RN 具体的触发时机我没有做详细的测试,但基本上把这个属性关掉就可以规避了。

7.FlatList

FlatList 主要是注意 3 个点:

  • FlatList 提供自定义的头部/底部/空白/分割线组件,比一般的 Web 组件封装更彻底一些
  • React 渲染列表的时候会要求加 key 以提高 diff 性能,但是 FlatList 封装的比较多,需要用 keyExtractor 这个 API 来指定列表 Cell 的 key
  • FlatList 性能优化的内容官网写的不是很好,我之前写了个更易懂的,有需求的同学可以了解一下

二、内置 API

本节内容主要是是对官网 React Native API 内容的补充,主要是说一些让人开发体验不爽的地方,帮助后来人避坑。

1.AppState

AppState 这个 API 在实际开发中主要是监听 APP 前后台切换的,这个 API 在 iOS 上表现符合语义,但是 Android 上就有问题了,因为 AppState 在 Android 端的实现其实是基于 Activity 的生命周期 的。

就比如说 AppState 提供的 background 这个状态,其实是基于 Activity 的 onPause() 的,但是根据 Android 的文档,onPause() 执行时有这么几种场景:

  • APP 切换到系统后台(符合预期)
  • 当前 RN 容器 Activity 上层覆盖了新的 Activity(不符合预期)
  • 当前 RN 容器 Activity 上层覆盖了 Dialog,例如权限申请弹窗(Dialog 本质上就是个半透明 Dialog)(不符合预期)

综上所述,使用 AppState 监听 APP 状态时要充分考虑 Android 的这些“异常”表现是否会引起程序 BUG。

2.Permissions

APP 平台的权限管理是一件很繁琐的事情,RN 官方只提供了 PermissionsAndroid,没有提供跨平台的权限管理 API,使用时很不方便。这里我建议使用 react-native-permissions 这个库,管理权限更便捷。

3.Event

RN 官网上没有暴露 Event 相关的 API,但是 RN 已经对外导出DeviceEventEmitter 这个「发布-订阅」事件管理 API,使用也很简单,如下案例使用即可。

import { DeviceEventEmitter } from 'react-native';

// 触发
DeviceEventEmitter.emit('EVENT');
// 监听
const listener = DeviceEventEmitter.addListener( 'EVENT', () => {});
// 移除
listener.remove()

4.Animated

RN 的动画 API,说实话掌握成本比较高,单官方 API 就涉及到 AnimatedLayoutAnimationEasinguseNativeDriver 等概念,而且文档分布比较分散,初学者很难在脑海里构建一个完整的脑图。

如果你想构建性能更高的动画,还得学习 react-native-gesture-handlerreact-native-reanimated 等第三方库的 API,学习成本直线飙升。

这里我推荐 React Native Animation Book 这本在线书籍,基本上算是手把手教学,看完之后就对 RN 的动画 API 有个整体的认识了。

三、第三方 Library

React Native 陆陆续续把一些非核心的组件交给社区维护,例如 webviewasync-storage 等。还有一些非官方但很好用的组件,例如 react-native-svgreact-native-camera 等等。

除了这些和 Native 相关的第三方库,JS 社区里宿主无关的 JS 库也是可以使用的,例如 lodashredux 等纯逻辑库。

由于第三方库太多了,所以我这里就不一一列举了。

四、特效篇

React Native 的 style 样式属性提供了基础的布局属性,例如 flexbox layout、fontSize 等等。但是很多 CSS3 的特效属性,React Native 基本上都得引入第三方库。我梳理了一下常用的几个 UI 特效要用到的属性和插件,方便开发者使用。

1.圆角效果

这个直接使用 View styles 属性的 borderRadius 即可,RN 同时也支持设置 View 四个角的单独弧度。

2.模糊效果

blur 效果要用到 @react-native-community/blur 这个 RN 官方社区库。这个 RN 模糊库比 CSS 的 blur() 属性更强大一些,CSS 只支持高斯模糊,这个库支持起码三种模糊效果,不过具体效果还是要和 UED 商议。

3.阴影效果

阴影可以用 RN 提供的 Shadow Props,但是它是分平台的:

  • iOS 提供了 shadowColorshadowOffsetshadowOpacityshadowRadius 四个属性,和 CSS 的 box-shadow 属性完全对标,可以满足绝大多数的场景
  • Android 只提供了 shadowColorelevation 两个属性,而且从严格意义上来说,elevation 其实是「仰角」的意思,是 Android 官方提供的属性,模拟现实中的从上向下的光照引起的阴影变化。虽然理论一套一套的,但是在现实开发中就会发现,elevation 搞出来的阴影非常丑,和 iOS 比起来完全是天壤之别。个人一般建议使用渐变替代阴影。

4.渐变效果

渐变要使用一个第三方库:react-native-linear-gradient,正如库名,这个仓库只提供「线性渐变」的解决方案,以个人经验,线性渐变在绝大部分情况下都足够了。如果要使用「径向渐变」,可以使用 react-native-svgRadialGradient 组件。

五、可视化篇

Web 平台除了最基础的 <p/> <img/> 标签,还支持 SVG、canvas 这些自由度较高的绘制 API。它们支持最多的就是可视化场景,例如各种自定义图像和图表。下面就简单介绍一下 RN 中对标 Web 的的一些第三方库。

1.SVG

RN 的 SVG 支持是基于 react-native-svg 这个仓库,就个人的使用体验来说,基本和 Web 的 SVG 功能没啥两样。除了自绘一些自定义 SVG,它更多的功能是作为底层库支持上层图表的使用。

2.类 canvas

RN 中是没有 canvas 这个概念的,市面上也没有很好用的 canvas 替代品。有开发者搞出了 react-native-skia,也有一些 demo 展示。但它目前其实还是一个实验性项目,上生产环境风险还是太大了。不过就我个人经验来说,很多绘制功能都能基于 SVG 实现,必须用 canvas 的情况应该并不多见。

基于 skia 你再把 flutter 集成进去,可以玩套娃游戏了 :)

3.OpenGL 支持

在移动端平台上,WebGL 就是浏览器平台对 OpenGL ES 的封装,RN 本身已经很贴近 Native 平台了,就没必要舍近求远支持 WebGL 了,直接支持 OpenGL ES 就好。

目前 RN 对 OpenGL 的支持是基于 gl-react 的,底层的适配层是基于 expo-gl。网上有个 gl-react 的 demo 教程,有需要的读者可以学习一下。

因为个人没做过 RN 3D 相关的需求,所以也无法对该库得出一个准确的评价,需要读者自行判断

4.图表功能

图表是个很现实的需求,在一些 B 端场景上经常会有报表需求。因为 RN 只有 SVG 支持比较完善,所以 RN 的图表基本都是基于 SVG 绘制的。

Web 上基于 SVG 的图表库有很多,但是 RN 能用到的可能没有几个。主要原因是 RN 和 Web 的宿主环境不一样,一些图表库可能会用到 Web 特供 API(例如 getElmentById),像 ECharts 这样的库 RN 肯定是用不了的。

可迁移使用的库一般要满足两个条件:

  • 纯逻辑D3.js 一些纯逻辑的库,只用到 JS 的语言能力,例如 d3-scale
  • 平台无关:直接基于 React 构建,没有用到平台特有 API,例如 victory-native

这里有一个基于 D3.js 实现的股票箱型图的视频教程,感兴趣的读者可以了解一下。

5.海报功能

海报分享是现如今非常常见的一个前端功能,网页基本是基于 canvas 生成分享海报的,RN 虽没有较好的 canvas API,但是有个不错的库——react-native-view-shot,可以把 RN 写的 View 生成一张图片。借用这个库就能在 APP 本地生成图片,转而实现海报功能。

推荐阅读

RN 性能优化系列目录:


如果你喜欢我的文章,希望点赞 收藏 在看 三连支持一下,谢谢你,这对我真的很重要!

欢迎大家关注我的微信公众号:卤蛋实验室,目前专注前端技术,对图形学也有一些微小研究。

也可以加我的微信 egg_labs,欢迎大家来撩。

📝 没 2 年 React Native 开发经验,你都遇不到这些坑的更多相关文章

  1. react native 5.54 出ios版本遇到的坑(应该是在xcode10下才会有的吧)记录。。。。。。 据说5.7已经修复了

    1. config.h找不到 rm -r ~/.rncache/cd node_modules/react-native/third-party/glog-0.3.4/./configure --ho ...

  2. 我的第一个React Native App

    我用了三天时间实现了一个相对比较完整的React Native 新闻发布类型的示例.应用做得很简单,但大多React Native的组件都有用到,今天做一个分享(由于我电脑是Windows系统,所以只 ...

  3. React Native入门遇到的一些问题

    本文示例参考自<React Native第一课> React Native官方文档中文版(含最新Android内容) 这里只大概记录下我的操作步骤和遇到的问题,一定要牢记下面这条: 如果你 ...

  4. Hybrid App 和 React Native 开发那点事

    简介:Hybrid App(混合模式移动应用)开发是指介于Web-app.Native-App这两者之间的一种开发模式,兼具「Native App 良好用户交互体验的优势」和「Web App 跨平台开 ...

  5. 关于React Native的那些坑

    好久没写博客了,特地把之前接触React Native时遇到的坑总结一下. 初始化一个React Native项目时,可能会遇到以下这些坑: 1.项目版本号与安卓模拟器中安装的 compileSdkV ...

  6. 一次掌握 React 与 React Native 两个框架

    此系列文章将整合我的 React 视频教程与 React Native 书籍中的精华部分,给大家介绍 React 与 React Native 结合学习的方法. 1. 软件开发语言与框架的学习本质 我 ...

  7. React Native学习方法论

    这是我技术公众号的第一篇文章,也是React Native系列文章的第一篇,对我的文章感兴趣的可以加我微信16230091进行关注. 本文表面上讲React Native(以下简称RN),实际上对于学 ...

  8. React Native入门指南

    转载自:http://www.jianshu.com/p/b88944250b25 前言 React Native 诞生于 2015 年,名副其实的富二代,主要使命是为父出征,与 Apple 和 Go ...

  9. 写给移动开发者的 React Native 指南

    本文原创版权归 简书 wingjay 所有,如有转载,请于文章篇头位置显示标注原创作者及出处,以示尊重! 作者:wingjay 出处:http://www.jianshu.com/p/b8894425 ...

随机推荐

  1. uniapp封装小程序雷达图组件实现

    效果图: view <canvas id="radar-canvas" class="radar-canvas" type="2d"& ...

  2. javaWeb常用面试题

    JDBC JDBC访问数据库的基本步骤是什么? 加载驱动 通过DriverManager对象获取连接对象Connection 通过连接对象获取会话,有2种方式Statement.PreparedSta ...

  3. Java Web基础 --- Servlet 综述(理论篇)

    摘要: Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.本文首先从请求/响应架构应用的大背景谈起 Servlet 的由来,明确 Ser ...

  4. ABC类IP地址

    A类IP地址一个A类IP地址由1字节的网络地址和3字节主机地址组成,网络地址的最高位 必须是"0", 地址范围从1.0.0.0 到126.0.0.0.可用的A类网络有126个,每个 ...

  5. 移动端动画——requestAnimationFrame

    window.requestAnimationFrame() 告诉浏览器--你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画.该方法需要传入一个回调函数作为参数,该回调函数会 ...

  6. adb shell 查看当前与用户交互的 activity

    adb shell dumpsys activity activities | grep mActivityComponent

  7. 一、部署sqlserver

    1.下载并挂载sqlserver镜像 2.填写秘钥:6GPYM-VHN83-PHDM2-Q9T2R-KBV83 3.默认下一步 4.勾选需要的功能 5.默认下一步 6.默认下一步 等待安装完成即可. ...

  8. noip模拟32

    \(\color{white}{\mathbb{山高而青云冷,池深而蛟穴昏,行以慎步,援以轻身,名之以:落石}}\) 开题发现 \(t1\) 80分特别好写,于是先写了 但是这个做法没有任何扩展性,导 ...

  9. Flask - 解决 app.run() 添加 host、port、debug 参数后运行不生效的问题

    问题背景 app.run() 添加了 host.port.debug 参数,运行后发现没有生效,咋肥事! 解决方案 要打开 debug 模式的话,勾选 FLASK_DEBUG 就好啦 再次运行,发现已 ...

  10. TCP头部格式和封装

    文章目录 12.3 TCP头部和封装 12.3.1 端口号 12.3.2 序列号 12.3.3 头部长度 12.3.4 相关控制位 12.3.5 窗口大小 12.3.6 校验和 12.3.7 选项字段 ...