React Native移动开发实战

978-7-115-47096-6
作者: 向治洪
译者:
编辑: 赵轩

图书目录:

详情

紧密围绕使用React Native框架开发移动app所需要的技能和实战技术全书从最基础的SCC、HTML标签和React 基本组件出发,并通过多种实例的讲解让读者真正理解这些知识,各实例均经过精心设计,操作步骤清晰简明,技术分析深入浅出,实例效果精美。

图书摘要

版权信息

书名:React Native移动开发实战

ISBN:978-7-115-47096-6

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    向治洪

  责任编辑 赵 轩

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


本书全面详尽地介绍了React Native框架的方方面面,内容涵盖React Native基础知识、环境搭建与调试、开发基础、常用组件、常用API、组件封装、网络与通信、混合开发、热更新与打包部署,以及两个实际案例的完整开发教程。这些丰富的内容不仅能让读者了解这款框架中涉及的各类概念,还能指导读者开发实践。

本书语言简洁,内容丰富,适合有一定Android、iOS原生开发基础和CSS基础的移动开发工程师学习。


近年来,随着移动互联网产业的持续快速发展,以及智能手机、智能电视等智能终端设备的普及,移动互联网应用获得了爆炸式增长。面对未来广阔的市场,运营商、互联网企业、设备生产商等产业巨头纷纷构建了移动互联网生态链,其中苹果公司和Google创造的移动互联网应用商业模式,激发了广大开发者开发移动互联网应用的热情。

众所周知,原生(Nutive)应用因其性能优秀、体验较好而获得了广大用户和开发者的欢迎。然而,原生应用开发周期长、支持设备有限等问题也困扰着开发者和商户,因而,跨平台移动应用开发成为技术开发者的重要追求。近年来,跨平台开发的呼声越来越高,已成为一种趋势。目前,移动应用的跨平台技术主要有两种。一种是基于Web的移动开发技术,只需要使用标准的HTML及JavaScript进行开发,然后使用移动终端安装的浏览器,即可实现应用的跨平台;另一种是使用特定的跨平台技术和框架,开发出能在各种主流移动操作系统上运行的APP应用程序。在React Native出现之前,国内外的全栈开发社区都在坚持不懈地寻求使用JavaScript和HTML、CSS技术体系开发跨平台移动应用,这些技术被统称为H5技术(HTML5技术)。作为Web时代的弄潮儿,Facebook也曾投入大量的人力物力,在移动H5技术上攻坚克难,虽然取得了一些进展,然而,这些基于JavaScript体系开发的移动应用始终达不到理想的效果。

React Native的出现,使开发者在跨平台移动应用的开发道路上向前迈了一大步。React Native是一款由Facebook公司推出的用来构建移动应用的JavaScript框架,是Facebook早先开源的界面渲染框架React在原生移动应用平台的衍生产物,目前支持iOS和Android两大平台。React Native倡导的“Learn once, write anywhere”(仅需学习一次,编写任何平台)也赢得了广大开发人员的青睐。虽然,新框架的引入不可避免地增加了学习成本,但是,相对于其他的跨平台技术而言,React Native的学习成本还是比较低的。截至2017年7月,在GitHub上React Native已获得了52000多个star,成为时下最受欢迎的跨平台移动应用开发框架之一。

在技术实现上,React Native抛弃了传统的浏览器加载思路,转而采用曲线调用原生API的思路来渲染界面,从而获得了媲美原生应用的体验。React Native具体实现思路如下:应用启动后会从服务器下载最新的JSBundle文件,然后通过本地的 JavascriptCore引擎对JS(Javascript缩写)文件进行解析,并利用Bridge映射到对应的原生API上,进而调用原生方法和UI组件来渲染界面。在语法上,React Native使用JSX来替代常规的JavaScript,这是一种很像XML的JavaScript语法扩展。因此,熟悉JavaScript类库的Web开发者可以使用React Native轻松地开发出移动应用。由于使用JSX编写的大部分代码可以实现平台间共享,因此,采用React Native开发可以大幅减少跨平台移动应用开发的工作量。同时,React Native框架采用模块化结构,使应用版本的更新迭代也异常简单。当然,React Native 也不是完美无缺的,但瑕不掩瑜,随着它的日趋成熟,React Native势必会成为跨平台移动应用开发的主流技术。

本书适当地介绍了一些原理性的概念,但并不深究,同时本书提供的不少案例,也将带领你快速地进入React Native的世界。雄关漫道真如铁,而今迈步从头越。相信通过学习本书,你一定会有所收获。

作者  


React Native基于React框架而设计,因此,了解React有助于我们更好地理解React Native。

React是由Facebook推出的前端开发框架,其本身作为MVC模式中的View层来构建UI,也可以以插件的形式应用到Web应用程序的非UI部分构建中,轻松实现与其他JS框架的整合。同时,React通过对虚拟DOM的操作来控制真实的DOM,从而得到页面的局部更新,提高了GPU渲染的性能,而React提出的模块化开发思路也大大提高了代码的可维护性。

React的官方地址是https://github.com/facebook/react。截至2017年4月,React获得了超过62K的star和11K的fork,这说明React得到了技术人员的普遍支持,正是由于这些原因,React.js和Vue.js、Angular.js成为了当今最流行的三大前端框架。

讲到React,就不得不提到组件(Component)的概念,它是React最基础的部分,其功能相当于AngularJS里面的Directive,或是其他JS框架里面的Widgets或Modules。Component可以认为是由HTML、CSS、JavaScript和一些内部数据组合而成的模块,当然Component也可以由很多其他的Component组建而成。不同的Component既可以用纯JavaScript定义,也可以用特有的JavaScript语法JSX创建而成。采用React进行项目开发,能够获得以下优势。

虚拟DOM(Virtual DOM)

传统的Web应用开发,一般都是通过直接操作真实DOM来进行更新操作的,如图1-1所示,但对DOM进行操作通常是比较昂贵的。而React为了尽可能减少对真实DOM的操作,采用了一种强大的方式来更新DOM,代替直接的DOM操作,这就是Virtual DOM,一个轻量级的虚拟DOM。

图1-1 传统的Web应用结构图

虚拟DOM其实是React抽象出一个对象,通过这个Virtual DOM可以更新真实的DOM,由这个Virtual DOM管理真实DOM的更新,如图1-2所示。简单来说,React在每次需要渲染时,会先比较当前DOM内容和待渲染内容的差异,然后再决定如何最优地更新DOM,这个过程被称为reconciliation。

图1-2 React Web应用结构图

除了性能方面的考虑,React引入虚拟DOM更重要的意义在于提供了一种新的开发方式来开发服务端应用、Web应用和手机端应用,如图1-3所示。

图1-3 虚拟DOM结构图

Components组件

虚拟DOM(virtual-dom)不仅带来了简单的UI开发逻辑,同时也带来了组件化开发的思想。所谓组件,即自己封装的具有独立功能的UI部件。React推荐以组件的方式去构成视图,并建议将功能相对独立的模块抽象为组件。例如,Facebook的instagram.com网站都采用React来开发,整个页面就是一个大的组件。

对于React而言,界面被分成不同的组件,每个组件都相对独立。在React开发中,整个界面可以看成是由大小组件构成,每个组件实现自己的逻辑部分即可,彼此独立,如图1-4所示。

采用组件化开发,往往具有以下特点:

图1-4 Components组件示意图

数据流(Data Flow)

React采用单向的数据流,即从父节点到子节点的传递,因此更加灵活便捷,也提高了代码的可控性。React单向数据流可以总结为以下流程:Action→Dispatcher→Stroe→View,如图1-5所示。

图1-5 React单向数据流流程图

JSX语法

JSX是React的核心组成部分,React使用JSX来替代常规的JavaScript。它使用XML标记的方式去直接声明界面,目的是通过各种不同的编译器将这些标记编译成标准的JS语言。使用JSX语法后,可以让组件的结构和组件之间的关系看上去更加清晰并且执行效率更高。

React Native(简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的UI框架React在原生移动应用平台的衍生产物,目前支持iOS和Android两大平台。

React Native可以基于目前大热的开源JavaScript库ReactJS来开发iOS和Android移动应用,因为往往只需要开发一套代码就可以满足iOS和Android,正如Facebook说的“Learn once, write anywhere”(仅需学习一次,编写任何平台),由于基于Web技术,React Natie开发起来可以像在浏览器那样随改即所见。

React Native的原理是在JavaScript中使用React抽象操作系统的原生UI组件,代替DOM元素来渲染界面,比如用<View>组件取代<div>,用<Image>组件替代<img>等。React Native主要运行着两个线程:主线程和JavaScript引擎线程,两个线程之间通过批量化的async消息协议来通信。

在UI方面,React Native提供跨平台的类似Flexbox的布局系统,还支持CSS子集。可以用JSX或者普通JavaScript语言,还有CoffeeScript和TypeScript来开发。运用React Native,我们可以使用同一份业务逻辑核心代码来创建原生应用运行在Web端、Android端和iOS端。

React Native相比Web开发或原生开发主要有以下特点:

APP占用体积小

随着业务的迭代,原生APP的体积越来越大,特别是一些老的APP,动辄上百兆,而采用React Native之后,占用体积会大大缩小,而且引入React Native可以实现持续开发。

实现跨平台开发

基于Web技术(HTML5/JavaScript)构建的移动应用速度快,开发周期短,但是体验较差,响应不及时;而使用原生开发,周期长,项目风险不可控。如何提高开发效率,节约人力成本。成为各大公司考虑的问题,而React Native的出现解决了上面的问题,只需要开发一套代码,便可以同时部署到Android和iOS两个移动平台上。

相对成熟的技术

随着Android/iOS的React Native陆续开源,原生提供的组件和API相对丰富,且实现技术基本一致,对于熟悉前端和原生APP开发的人员来说很容易上手。而React Native通过JavaScriptCore将JS转换为原生APP组件进行渲染,其用户体验也可媲美原生APP。

支持动态更新

在原生APP开发中,Android平台可以通过插件化实现热更新。在iOS平台上,热更新策略是严令禁止的(如JSPatch/wax/rollout等技术),而采用React Native技术完全可以满足要求,而又不触碰苹果的底线。

使用JavaScript开发移动APP的想法来源于最近几年市场对于移动应用需求的增长,为了快速开发一款可以使用,而体验又不是那么糟糕的APP,很多公司投入大量人力开发跨平台应用。而在这些公司当中,Facebook无疑是做得最好、最成功的。

为了更好地理解React Native,我们需要对React Native的工作原理和整体架构有一个了解,如图1-6所示。

图1-6 React Native整体框架图

如图,React Naitve框架分为3层,分别为:JSX环境层、虚拟DOM层、具体的平台层。这里面最重要的就是虚拟DOM层。

在React中,Virtual DOM就像一个中间虚拟层,位于JavaScript和实际渲染页面之间。对于JS开发者来说,只需要专注于UI层的绘制即可,不需要特别关心具体平台的实现。

虚拟DOM是一个 JavaScript 的树形结构,主要包含React元素和模块。组件的DOM结构就是映射到对应的虚拟DOM上,React通过渲染虚拟DOM到浏览器,使得用户界面得以显示。React之所以更新界面高效,是因为React的虚拟DOM采用了batching(批处理)和高效的Diff算法,采用Diff算法,可以将时间复杂度从O(n^3)降到O(n),从而提高界面构建的性能。当需要更新组件的时候,会通过Diff算法寻找到要变更的DOM节点,然后通知浏览器更新变化的内容。

虚拟DOM更新视图的过程可以总结为:状态变化→计算差异(Diff算法)→界面渲染。其渲染的原理如图1-7所示。

图1-7 虚拟DOM更新原理图

在界面渲染过程中,React Native针对不同的平台调用原生API去渲染界面,例如iOS平台调用其原生的API去渲染iOS界面,Android平台调用其原生API去渲染Android界面,而不是直接渲染到浏览器的DOM上,这使得React Native不同于基于Web视图的跨平台应用开发方案,因而,采用React Native开发的APP,体验更加接近原生APP。

虚拟DOM和MVVM的对比

虚拟DOM只是MVVM框架的一种实现方案,二者没有好坏之分。在流行的前端框架中,除了React采用虚拟DOM之外,其他MVVM系框架,如Angular、Vue、Avalon,采用的都是数据绑定。

何为数据绑定?简单来说,就是通过观察Directive/Binding对象数据变化,并保留对实际DOM元素的引用,当有数据变化时进行对应的操作。React检查是DOM结构层面的,而MVVM的检查则是数据层面的。MVVM的性能检测也根据检测层面的不同而有所不同:Angular的脏检查使得任何变动都会产生固定的更新的代价;而Vue/Avalon采用的依赖收集,使得在JS和DOM层面都会产生更新。

上面提到两个概念—脏检查和依赖收集。

可以看出,Angular效率低的地方在于任何小变动都会引起界面的重绘,但是,当所有数据都变化的时候,Angular并不吃亏。依赖收集在初始化和数据变化的时候都需要重新收集依赖,在数据流比较小的时候几乎可以忽略,但在数据量比较大的时候就会产生一定的消耗。相比之下,React的变动检查则是DOM结构层面的,即使是全新的数据,只要渲染结果没有变化,也不需要重新绘制。

Angular和Vue都提供了重绘的优化机制,即有效地复用实例和DOM元素。在优化的版本中,Angular和Vue采用了track by $index技术后比React的效率更高。

所以在框架选择和技术性能分析的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合,以及DOM、脏检查MVVM、数据收集MVVM在不同场合各自的表现和优缺点,具体表现和区别如下。

曾经大部分开发者以为可以通过Web技术来实现跨平台移动开发,却因为性能限制或其他问题而放弃,最终,不得不针对多个平台开发多个版本,这违背了跨平台开发的初衷。而React Native的出现让跨平台移动端开发再次回到人们的视野中,而它提倡的“Learn once, write anywhere”也赢得了广大开发人员的青睐。相比传统的H5技术,React Native获得了更加接近原生应用的体验。

为了方便理解,笔者将跨平台技术分为四大流派。

Web流,如大家熟知的PhoneGap/Cordova等技术,它将原生的接口封装后暴露给JavaScript,然后通过系统自带的WebView运行,也可以使自己内嵌Chrome内核。

Web流缺点是性能差、渲染速度慢。说它Web性能差,主要说的是在Android下比较差,在iOS下已经很流畅了。

性能差的主要原因是,在Android和iOS的早期设备中,由于没有实现GPU加速,所以会造成每次重绘界面的卡顿。

而造成渲染慢的第二个原因是:CSS过于复杂。因为从实现原理上看,Chrome和Android View并没有本质上的差别,但过于复杂的CSS会加重GPU的负担。那是不是可以通过简化CSS来解决呢?实际上还真有人进行了这种尝试,比如著名的Famo.us,其最大的特色就是不使用CSS,只能使用固定的几种布局方法,完全依靠JavaScript来写界面,它能有效避免低效的CSS代码,从而提升机器性能。

造成绘制缓慢的第三个原因是,业务需求的复杂,比如超长的ListView商品展示。因为DOM是一个很上层的API,使得JavaScript无法做到像Native那样细粒度地控制内存及线程,所以难以进行优化,特别是在硬件较差的机器上。

上面三个问题现在都不好解决。其实除了性能之外,Web流更严重的问题是功能缺失。比如iOS 8就新增4000多个API,而Web标准需要漫长的编写和评审过程,而等到Web审核通过,即便是Cordova这样的优秀的框架,或者自己封装也是忙不过来的。所以为了更好地使用原生系统新功能,Native是最快的选择。

不同平台下的官方语言不一样,并且平台对官方语言的支持最好,这就导致对于同样的逻辑,我们需要写多套代码。比如Android平台用Java,iOS用Objective-C或者Swift。于是就有人想到了通过代码转换的方式来减少重复的工作量,这就是代码转换流。

这种方式虽然听起来不是很靠谱,但它的成本和风险都是最小的,因为代码转换后就可以用官方提供的各种工具了,和普通开发区别不大,而且转换后,利用原生的优势,可以减少兼容性问题。

目前存在以下几种代码转换方式。

将Java转成Objective-C

2objc是一款能将Java代码转成Objective-C的工具,据说Google内部就是使用它来降低跨平台开发成本的,比如Google Inbox项目就号称通过它共用了70%的代码,效果很显著。有了2objc,我们就可以先开发Android版本,然后再开发iOS版本。

将Objective-C转成Java

MyAPPConverter是一款将Objective-C代码转换成Java代码的工具,比起前面的2objc,MyAPPConverter还打算将UI部分也包含进来,从它已转换的列表中可以看到还有UIKit、CoreGraphics等组件,使得有些应用可以不改代码就能转换成功。

XMLVM

除了上面提到的源码到源码的转换,在代码转换流中,还有XMLVM这种与众不同的转换方式,它首先将字节码转成一种基于XML的中间格式,然后再通过XSL来生成不同语言,目前支持生成C、Objective-C、JavaScript、C#、Python和Java。

虽然基于中间字节码可以支持多语言,但是这种方式也有一些问题,例如生成代码不可读,因为很多语言中的语法会在字节码中被抹掉,并且是不可逆的,所以不利于代码的调试和发现问题。

综上所述,虽然代码转换这种方式风险小,但对于很多小APP来说其实共享不了多少代码,因为这类应用大多数围绕业务来开发的,大部分代码都和业务逻辑耦合,所以公共部分不多,其意义不大。

编译流比代码转换流的代码转换更进一步,它直接将某个语言编译为普通平台下能够识别的二进制文件。采用这种方式主要有以下特点。

优点

缺点

常用的编译流方案如下所示。

C++方案

因为目前Android、iOS和Windows Phone都提供了对C++开发的支持。特别是C++在实现非界面部分,性能是非常高的。而如果使用C++实现非界面部分,还是比较有挑战的。这主要是因为Android程序的界面绝大部分是Java编写的,而在iOS和Windows Phone平台下可以分别使用C++的超集Objective-C和C++/C#来开发。要解决使用C++开发Android应用程序界面的问题,目前主要有两种方案。

第一种方式虽然可行,但是代码冗余高,实现过于复杂。那第二种方式呢,比如JUCE和Qt就是用代码实现的。不过在Qt的方案中,Android 5版本或更高版本环境下,很多效果都没法实现,比如按钮没有涟漪效果。根本原因在于它是通过Qt QUIck Controls的自定义样式来模拟的,而不是使用系统UI组件,因此它享受不到系统升级自动带来的界面优化。

当然我们可以使用OpenGL来绘制界面,因为EGL+OpenGL本身就是跨平台的。并且目前大多数跨平台游戏底层都是这么做的。

既然可以基于OpenGL来开发跨平台游戏,那么,是否能用它来进行界面开发呢?当然是可行的,而且Android 4的界面就是基于OpenGL的,不过它并不是只用OpenGL的API,那样是不现实的,因为OpenGL API最初设计并不是为了实现2D界面,所以连画个圆形都没有直接的方法,因此Android 4中是通过Skia将路径转换为位置数组或纹理,然后再交给OpenGL从而完成界面渲染的。

然而直接使用OpenGL绘制界面,不仅实现的代价大,而且目前支持的平台少。因此对于大多数应用来说自己实现界面是很不划算的。

Xamarin

Xamarin是从Mono发展而来,它用C#来开发Android及iOS应用,因为相关工具及文档都挺健全,因而发展得还不错。在UI界面方面,它可以通过调用系统API来使用系统内置的界面组件,或者基于Xamarin.Forms开发定制要求不高的跨平台UI。

从实现的方式来讲,iOS下是以AOT的方式编译为二进制文件的;而在Android平台上是通过内嵌的Mono虚拟机来实现,所以Xamarin是跨平台开发的不错选择。

对于熟悉C#的团队来说,Xamarin是一个很不错的方案,但这种方案最大的问题就是相关资料不足,遇到问题很可能搜不到解决方案,并且当前第三方库太少,加之Xamarin本身有些bug,所以让我们静待Xamarin做得更好吧。

Go

Go做为后端服务开发语言,专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++程序的速度,而且更加安全、支持并行进程。Go从1.4版本开始支持开发Android应用(1.5版本支持iOS)。虽然能同时支持Android和iOS,但是目前可用的API很少,Go语言仍然专注于后端开发。

目前,Android的View层完全是基于Java写的,要想用Go来完成界面的开发不可避免要调用Java代码,而在这方面Go还没有简便的实现方式,目前Go调用外部代码只能使用Cgo,通过Cgo再调用jni,这就不可避免地需要写很多的中间件。而且Cgo的实现本身就对性能有损失,除了各种无关函数的调用,它还会锁定一个Go的系统线程,这会影响其他gorountine的运行,如果同时运行太多外部调用,甚至会导致所有go线程处于等待状态。

所以,目前使用Go开发跨平台移动端应用并不靠谱。

编译流是将代码编译为不同平台下的二进制文件,而另一种更彻底的做法是:通过虚拟机来支持跨平台运行,比如JavaScript和Lua都是天生的内嵌语言。不过使用虚拟机进行跨平台开发最普遍的两个问题是:性能损耗;虚拟机本身也会占据不小的空间。

Java虚拟机

说到虚拟机,大家肯定首先想到的是Java,因为Java一开始就是为跨平台而设计的,Sun的J2ME早在1998年就有了,在iPhone手机出来之前,很多小游戏都是基于J2ME开发的。前几年,微软为了支持移动端项目的发展,提供了一套将Android和iOS代码快速转移到Windows Phone的工具,不过后来不了了之。

前面提到C#和Java在iOS端的方案都是通过AOT的方式实现的,目前还没见到有Java虚拟机相应的方案,主要原因是iOS方面的限制。

Titanium/Hyperloop

Titanium和PhoneGap几乎是同时期的著名跨平台方案,和PhoneGap最大的区别是:它的界面没有使用HTML/CSS,而是自己设计了一套基于XML的界面框架Alloy。Titanium的代码风格如下:

APP/styles/index.tss
".container": {
backgroundColor:"white"
},
// This is APPlied to all Labels in the view
"Label": {
width: Ti.UI.SIZE,
height: Ti.UI.SIZE,
color: "#000", // black
transform: Alloy.Globals.rotateLeft // value is defined in the alloy.JS file
},
// This is only APPlied to an element with the id attribute assigned to "label"
"#label": {
color: "#999" /* gray */
}

虽然学习成本低,但Titanium同样面临着其他跨平台框架都存在的挑战:缺乏第三方库支持、对外的API较少。Titanium也意识到了这个问题,所以目前在开发下一代的解决方案Hyperloop,它可以将JavaScript编译为原生代码,这样开发者可以方便地调用原生API。比如调用iOS的写法如下:

@import("UIKit");
@import("CoreGraphics");
var view = new UIView();
view.frame = CGRectMake(0, 0, 100, 100);

这个方案和之前讲到的Xamarin如出一辙,也是将JavaScript翻译为Objective-C,然后交由官方系统运行。不过这个项目已经开发了快三年了,但至今仍然是试验阶段,笔者不建议尝试。

React Native

React Native是由Facebook开源的基于JavaScript和React搭建的一套跨平台开发框架。在设计之初,React Native采用的方案就是在不同平台下使用平台自带的UI组件来完成界面的绘制,再加上它采用JavaScript和React等前端语言来开发,所以获得了不少前端程序员的青睐。

有人说,React Native采用JS等前端技术来开发移动APP是回归H5,但其实React Native和Web扯不上太多关系,React Native虽然借鉴CSS中的Flexbox、navigator、XMLHttpRequest等API的写法,但是大部分还是通过原生的组件或者自己封装的组件来开发的。就像Facebook的内部软件Facebook Groups,iOS版本很大一部分基于React Native开发,其中用到了不少内部通用组件。

React Native相比传统原生开发,学习成本还是比较低的,熟悉JavaScript的开发者可以迅速实现界面,而使用标签加CSS样式表方式绘制的界面,远比原生使用代码绘制的界面更加易读,并且一套界面同时满足Android和iOS平台,这对于讨厌绘制界面的开发者来说是多么的诱惑。再加上React Native师出名门,截至目前,React Native已更新到0.4.4版本,并且趋于稳定。由于其更加接近原生的体验,国内一些大厂纷纷加入,诸如阿里、腾讯、美团等纷纷开始使用React Native改造一些应用型APP。

所以,不管是对于个人还是团队,现在跨平台开发做得最好的就是React Native,并且随着开源力量的加入,React Native会发展得越来越好。

使用React Native开发跨平台移动APP是一个令人振奋的事情,相比其他跨平台方案,React Native在不牺牲用户体验和应用质量的前提下,提高了开发效率,使用一套代码即可实现在Android、iOS和Web平台上运行,节约了成本得到了广大移动开发者的追捧。

本章主要从React Native的发展历程和工作原理等方面对React Native做了一个简单的介绍,并横向比较了当前主流的跨平台方案。纵观目前的跨平台方案,你会发现React Native是目前最好的跨平台技术,如果你的团队正在进行跨平台开发或者考虑跨平台开发,不妨试试React Native。


工欲善其事,必先利其器,在进行正式开发之前,首先需要搭建好相关的开发环境。搭建React Native开发环境,需要如下软件。

安装Node.Js

从官网下载Node.js(官网地址:https://nodejs.org/en/),如图2-1所示。建议设置npm镜像以加速后面的过程。node安装命令如下:

npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global

图2-1 Node.js下载与安装

安装完成后,我们输入node-v,如果输出版本号,说明安装成功,如图2-2所示。

图2-2 查看Node版本

安装npm

npm是一个包管理工具,用来管理React中依赖的包,可以理解为一个项目结构的管理工具,作用类似于maven、gradle等。安装命令如下:

npm install -g react-Native-cli

如果已经安装过,可以使用如下命令进行升级:

npm install npm@latest -g

安装完Node后建议设置下npm镜像(淘宝镜像)以加速项目的构建,镜像命令如下:

npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global

安装Yarn

Yarn是Facebook提供的替代npm的包管理工具,可以加速node模块的下载和构建。相比npm,Yarn具有速度快,离线模式,版本控制等优势。安装Yarn的命令如下:

npm install -g yarn

使用Yarn下载React Native的命令如下,具体如图2-3所示。

npm install -g yarn react-Native-cli

上面的两种方式,不管哪种都可以下载React Native环境依赖包,然后静静地等待下线即可。

图2-3 使用Yarn下载React Native

安装Homebrew

Homebrew用于在Mac上安装一些OS X没有的UNIX工具(比如著名的wget)。React Native包管理器同时使用了node和watchman环境,所以上面的软件还可以使用Homebrew来安装,命令如下:

brew install node
brew install flow
…

安装Watchman

Watchman是由Facebook提供的监视文件系统变更的工具,此工具可以快速捕捉文件的变化从而实现实时刷新,以便提高开发的性能。Watchman的安装命令如下:

brew install watchman

至此,React Native的基础环境就搭建好了,为了将应用部署到移动设备上,还需要配置Android、iOS相关的运行环境。

React Native版本升级

React Native作为开源的移动跨平台框架,在很多细节上还不是很完善,所以版本迭代更新的速度相对较快。为了更好地开发出高质量的移动应用,需要不断地对React Native版本进行升级。

首先,使用命令查看本地的版本,命令如下:

react-native --version

然后,使用npm包管理命令查看React Native版本信息,命令如下,具体如图2-4所示。

npm info react-native

图2-4 查看版本信息

使用升级命令直接升级到指定版本,如下:

npm install --save react-native@0.45

升级完成之后,最常见的错误就是依赖的模块版本不统一,为此,根据提示升级React等相关模块即可。然后运行如下命令:

react-native upgrad

对于一些老项目,版本跨度比较大,建议对项目进行备份,将老项目的相关逻辑代码拷贝到新建的项目中,拷贝的内容大体如下:

iOS文件目录

Android文件目录

至此,React Native的升级操作就完成了。假如升级到最新版本后不是特别稳定,想要回到之前的版本,有两种方式:第一种是修改package.json文件;第二种是执行命令npm install --save react-native@版本号。经过上述操作之后,不要忘了更新相关的依赖文件,如果降级之后报错,建议删除node-modules文件夹,然后在使用npm install命令重新更新依赖文件。

安装Atom

Atom是专门为软件开发工作者推出的一款跨平台文本编辑器,如图2-5所示。它具有简洁和直观的图形用户界面,并有很多有趣的特点:支持CSS、HTML和JavaScript等网页编程语言;支持宏,自动完成分屏功能,集成了文件管理器等功能和优点。

打开Atom的官网(https://atom.io/),当然你也可以到国内的镜像地址下载,比如淘宝国内镜像地址:https://npm.taobao.org/mirrors/atom/1.7.2/

React Native官方推荐Atom+Nuclide来开发。Atom集成Nuclide的步骤如下:

点击菜单栏【Atom】→【Preferences】,或者使用快捷键【command+,】打开设置面板,然后在Install Packets的输入框中,输入Nuclide,点击【install】,如图2-6所示。安装完成之后就可以在Atom的工具栏看到Nuclide插件,如图2-7所示。

图2-5 Atom编辑器

图2-6 Atom安装Nuclide插件

图2-7 Nuclide安装结果

到此,React Native开发所需的IDE环境就安装完成了,接下来就可以使用IDE编写代码了。

在创建项目方面可以使用IDE辅助创建React Native项目,也可以使用命令方式创建。使用命令方式创建项目,首先创建项目工作空间,然后打开Mac终端,输入如下命令创建项目,如图2-8所示:

react-Native init Demo(项目名)

然后等待npm构建项目即可。

图2-8 使用命令创建项目

当项目构建完成之后,使用Atom导入新建的项目就可以开始编写代码了。如果使用WebStrom作为React Native开发IDE,则比较简单。

使用快捷键【commad+shift+p】打开面板,运行命令“React Native Packager”,或者使用图形化界面,依次点击【Nuclide】→【React Native】→【Start Packager】启动打包操作,如图2-9所示。

图2-9 启动React Native

打开终端运行项目,先定位到项目所在的位置,然后使用如下命令运行项目:

//运行iOS
react-Native run-ios
//运行Android
react-Native run-android

如果要在真机上运行iOS应用,则需要准备一台装有Mac系统的电脑,同时还需要一个Apple ID。如果需要把应用发布到App Store,那么还得去苹果开发者网站购买一个开发者账户(在自己手机上测试则不用)。要想在真机上运行iOS应用,你可以将USB连接至电脑,或者在Xcode的设备管理中添加你的设备。然后你就可以在你的真机上使用iOS应用或者调试应用了,如图2-10所示。

Android设备只需要使用USB安装即可。如果需要使用真机调试,摇晃设备就可以打开开发者菜单,将其中的【localhost】改为电脑的IP地址,启用开发者菜单中的【Debug JS Remotely】选项即可开启调试功能。

图2-10 运行iOS项目

目前React Native 在iOS环境下需要Xcode7及更高版本,使用 Xcode 打开React Native项目的iOS文件夹中,选中.xcodeproj文件导入项目文件即可,如图2-11所示。导入后的项目结构如图2-12所示。

图2-11 导入iOS项目

图2-12 iOS项目结构

使用快捷键【command+R】或者直接点击运行按钮运行项目可能会报错,这时候你需要使用命令先启动React Native相关依赖环境。启动命令如下:

react-Native start

相比iOS的环境依赖,Android的环境依赖就复杂得多,对应的官方配置文档地址为:http://facebook.github.io/react-Native/docs/android-steup.html。配置Android依赖环境,总体来说分为三步:安装Java环境,安装Android SDK环境,配置其他Android环境。

首先,需要安装配置Java和Android环境。

❶ 下载并安装最新版本的JDK,请注意选择的是x86还是x64版本,JDK的bin目录加入系统PATH环境变量中。JDK下载地址为:http://www.oracle.com/technetwork/java/javase/downloads/index-JSp-138363.html。

❷ 安装Android SDK环境,可以单独安装Android SDK,也可以通过Android Studio一并安装。这里直接使用Android SDK一并安装。Android Studio的下载地址为:http://www.android-studio.org/。然后配置Android相关环境变量。

❸ 打开Android SDK管理器,如图2-13所示。确保选中以下选项。

图2-13 Android SDK管理器

接下来安装模拟器,推荐使用Genymotion,这是一款强大的Android模拟器,下载地址:http://www.genymotion.net/。在Android Studio配置Genymotion 插件方面,使用快捷键【command+,】,或者依次点击【Android Studio】→【Preferences】→【Plugins】,搜索Genymotion插件并安装,如图2-14所示。安装完成之后,打开Android studio,点击Genymotion插件图标配置相关信息即可。

图2-14 Android Studio安装Genymotion插件

打开Android Studio导入React Native项目下的Android文件,如图2-15所示。

图2-15 导入Android项目

定位到项目目录,使用命令npm start启动React Native相关依赖环境,然后使用命令react-native run-android启动Android项目即可,如图2-16所示(注意,运行命令前先启动Android模拟器)。

图2-16 Android运行React Native项目

Windows环境下搭建React Native开发环境的步骤和Mac大体相同,在Windows环境下搭建React Native环境,依然需要Node、npm、Yarn、Watchman等环境的支持。不同之处在于Mac使用npm或者Yarn下载React Native,而在Windows环境下,则直接使用git克隆React Native到本地即可。克隆命令如下,具体见图2-17。

git clone https://github.com/facebook/react-Native.git

图2-17 使用git克隆React Native到本地

进入React Native目录下的react-native-cli目录,输入如下命令即可安装相关依赖包到全局环境中。

npm install <Name>-g

当然,除了如图2-18介绍的插件外,读者还可以根据实际需要安装一些其他插件,这些插件能提升React Native的开发效率,带来事半功倍的效果。

图2-18 安装相关插件

在React Native项目中,由于项目同时支持Android和iOS,所以我们会看到完整的Android和iOS项目结构。我们可以通过Android Studio 和 Xcode来打开相应的项目,在混合开发的时候,往往需要对原生的代码进行编辑,这时候,打开Android Studio和Xcode编写差异化代码即可。

当新建一个React Native项目后,使用IDE打开后看到的项目目录结构如图2-19所示。

图2-19 React Native项目结构

React Native项目文件组成及相关说明见表2-1。

表2-1 React Native文件表

名称

功能描述

__tests__

测试文件夹

android

Android文件所在目录,包含Android Studio项目环境文件

iOS

iOS文件所在目录,里面包含XCode项目环境文件

node_modules

基于node文件依赖系统产生的相关依赖和第三方lib

watchmanconfig

Watchman的配置文件,Watchman用于监控文件变化

flowconfig

flow的配置文件,flow用于代码静态检查

buckconfig

buck的配置文件,buck是Facebook开源的高效编译系统

index.android.js

Android程序入口文件

index.ios.js

iOS应用入口文件

package.json

项目基本信息以及依赖信息

其中index.android.js和index.iOS.js文件分别为Android和iOS的启动入口文件。React Native项目中所依赖的第三方库则被统一放在node_modules文件夹下,由package.json进行统一管理。

React Native项目中,同时包含Android和iOS,iOS的项目结构和原生的项目结构一致,其项目结构如图2-20所示。

图2-20 iOS项目结构

React Native文件iOS目录如表2-2所示。

表2-2 iOS文件表

名称

功能描述

build

项目的编译文件

shop

iOS对应项目所在的位置

shop-tvOS

tvOS对应的项目文件

xcodeproj

iOS项目工程启动文件

或许,读者会有疑问,在index.ios.js注册启动文件后,iOS是如何启动原生视图的呢?答案在APPDelegate.m文件中。打开APPDelegate.m,在APPDelegate.m中声明的根视图中有如下代码:

RCTRootView *rootView = [[RCTRootView alloc] 
initWithBundleURL:JSCodeLocation
moduleName:@"Shop"
initialProperties:nil
launchOptions:launchOptions];

React Native库将其所有的类名使用RCT作为前缀,也就是说RCTRootView其实是React Native的类。而在iOS中,RCTRootView表示React Native的根目录。APPDelegate.m通过将视图添加到UIViewCotroller中并渲染到屏幕上。例如,在本示例项目中,打开index.ios.js,在最后一行看到代码中暴露Shop组件,从而完成渲染工作。相关代码如下:

APPRegistry.registerComponent('Shop', () => Shop);

在React Native中,Android的项目结构和原生应用项目结构是一致的,其项目目录结构如图2-21所示。

图2-21 Android项目结构

Android项目文件及说明如表2-3所示。

表2-3 Android文件表

名称

功能描述

app/build

app模块build编译输出的目录

app/build.gradle

app模块的gradle编译文件

app/app.iml

app模块的配置文件

app/proguard-rules.pro

app模块的proguard文件

build.gradle

项目的gradle编译文件

settings.gradle

项目中的配置文件

gradlew

脚本文件,可以在命令行执行打包

local.properties

本地配置信息,如sdk、ndk配置

External Libraries

项目依赖的Lib,编译时自动下载

index.android.js作为Recott Ncotive项目Andrad端的启动入口,是如何启动原生视图的呢?正如APPDelegate.m之于iOS,Android的入口在MainActivity文件中,其核心的方法在getMainComponentName()中:

protected String getMainComponentName() {
   return "Shop";
}

除了上面介绍的文件外,React Native项目中所依赖的包都会统一放在node_modules文件夹下。关于使用React Native进行混合开发过程中的一些细节,后面章节将慢慢介绍。

在React Native开发中,除了需要原生开发工具Xcode和Android Studio之外,推荐的开发工具有Sublime、Webstorm以及官网推荐的Atom和VSCode。下面主要对React Native开发中用到的开发工具Atom和Webstorm做一些简单的介绍,读者可以根据喜好自行选择。

Atom是由Github打造的下一代编程开发利器,支持Windows、Mac OS X、Linux三大桌面平台,免费且开源。Atom 本质上是一款文本编辑器,而不是一款IDE,所以使用它开发React Native需要配合Nuclide一起使用。

Atom的官网为:https://atom.io/,读者可以到官网下载Atom安装包,如果网速较慢,还可以访问国内淘宝的镜像网站:https://npm.taobao.org/mirrors/atom/1.7.2/,点击相应的版本下载并安装,如图2-22所示。

图2-22 Atom官网

Nuclide是Facebook在Atom的基础上开发的一款插件IDE,可以用来开发React Native、iOS和Web应用,目前暂不支持Windows,只支持Mac OS X和Linux系统环境。Nuclide内置了对React Native的支持,包括代码自动补全、代码诊断等功能。而官方也推荐使用Atom+Nuclide来开发React Native应用。

Nuclide项目官方地址为:https://github.com/facebook/nuclide,打开后便可看到相关介绍,如图2-23所示。

图2-23 Nuclide官方介绍

在Atom中安装和使用Nuclide插件主要有以下几个步骤。

安装Nuclide

❶ 点击菜单栏:【Atom】→【Preferences】,或者使用快捷键【command+,】在Install Packets的输入框中输入nuclide,然后点击【install】,如图2-24所示。当然也可以使用命令安装,命令如下:

apm install nuclide

图2-24 安装Nuclide插件

❷ 安装完成之后,将在Atom的工具栏中看到Nuclide标签,如图2-25所示。

图2-25 Nuclide插件

❸ 安装Nuclide之后,会安装一大堆依赖包,如果默认没有安装,可以手动安装。依次选择【Packages】→【Settings View】→【Manage Packages】,如图2-26所示。搜索nuclide,进入设置,勾选【Install recommended packets on startup】即可。

图2-26 Nuclide依赖包管理

使用Nuclide运行项目

项目开发完成后,启动React Native项目主要有两种方式:一种方式是使用命令方式启动,而另一种方式就是直接利用IDE的相关图形化界面启动。使用命令方式启动的步骤如下,使用快捷键【command + shift + p】打开终端面板【command pafette】,输入如下打包命令,具体如图2-27所示。

react native start packer

图2-27 命令方式启动项目

如果使用Nuclide的图形化界面来运行项目,则可以依次选择【Nuclide】→【React Native】→【Start Packger】选项即可,如图2-28所示。

图2-28 图形界面方式启动项目

不管使用哪种方式,都可以启动React Native,上述方式无需定位到项目目录,也不涉及任何命令,相比命令方式,使用Nuclide启动React Native更加方便。

WebStorm是JetBrains公司开发的Javascript集成开发环境,可以用于客户端应用开发以及Web开发,目前,WebStorm支持Windows、Mac OS X、Linux三大桌面平台。最新版的WebStorm还支持界面化创建项目、界面化运行及调试功能,这对于习惯了Android Studio和Xcode界面化开发的人来说的确是不小的惊喜。

WebStorm的官网地址为:https://www.jetbrains.com/Webstorm/,下载相应的版本安装即可,如图2-29所示。需要注意的是,WebStorm只支持30天的试用时间,可以使用“license server”方式激活,激活server地址为:http://idea.imsxm.com/。

图2-29 WebStorm下载

最新版本的WebStorm默认支持JSX语法,并且其拥有强大的插件库,如代码提示和自动补全插件(ReactNative-LiveTemplate)、代码格式化插件以及配置WebStorm启动应用插件等。对于习惯了idel系列工具的开发者来说,使用WebStorm来开发React Native会是一个不错的选择。

除此之外,WebStorm在最新版本中默认添加了对React Native环境的支持,开发者可以直接使用WebStorm新建项目(见图2-30)、运行项目和调试项目(见图2-31)等。同时,WebStorm还有强大的日志系统,我们可以使用WebStorm自带的控制台查看相关日志,这对于我们理解应用的运作也是非常有好处的。

除了提供强大的插件库和默认对React Native的支持之外,WebStorm也支持使用图形化界面运行、调试应用,其强大的代码提示功能对于习惯了Xcode和Android Studio的APP开发者来说,可谓得心应手。

图2-30 使用WebStorm创建项目

图2-31 使用WebStorm运行、调试项目

在项目开发过程中,由于各种原因,遇到的问题往往是不可预知的,为了更好地发现程序中的bug,软件开发人员可以通过对程序设置断点来定位问题,进而修复bug。

当我们使用JavaScript开发Web产品时,有一些常用的调试JavaScript的技巧和工具,它们同时也适用于React Native开发中的调试工作,因此了解JavaScript调试技巧可以让我们更快速地调试React Native应用程序。

console.log日志

对于大多数的软件开发工作而言,日志调试是不可缺少的代码调试方式之一。在Web开发中,在代码中添加console.log日志输出是软件开发流程中的一个潜在环节,它可以让开发人员更方便地了解代码的执行流程。

不管是Xcode(iOS IDE)还是Android Studio(Android IDE),它们的控制台都可以打印我们想要的日志信息,前提是你在代码中添加了相关的日志。Xcode控制台日志如图2-32所示。

图2-32 Xcode控制台日志

与Xcode类似,Android Studio也提供了类似的日志输出窗口,并且还可以根据自己的需要进行条件筛选,如图2-33所示。

图2-33 Android Studio控制台日志

对于原生开发而言,Xcode和Android Studio是最好的选择,然而对于Web开发而言,借助浏览器进行代码的调试是一个不可忽略的技巧、具体使用的时候,激活开发者菜单,在开发者菜单选择【Debug in Chrome】,打开一个新的标签页:http://localhost:8081/debugger-UI。在Chrome中,按下组合快捷键【command+option+i】或选择【视图】(View)→【开发者】(Developer)→【开发工具】(Developer Tools),切换到开发工具控制台,就可以在Chrome开发者工具的控制台中看到输出的日志信息了。打开【有异常时暂停】(Pause On Caught Exceptions)选项,能够获得更好的开发体验。Chrome调试界面如图2-34所示。

图2-34 Chrome控制台日志

需要注意的是,在Chrome中并不能直接看到APP的用户界面,而只能提供console的日志输出,以及在sources项中断点调试JS脚本,如图2-35所示。当你开启Chrome调试工具来调试React Native之后,Chrome便会通过React Native包管理器使用标准的<Script>标签来执行相同的JavaScript代码。包管理器通过WebSocket进行设备与浏览器之间的通信。

图2-35 Chrome控制台日志

JavaScript调试器

就像开发Web应用程序一样,在使用JavaScript调试器的时候,在浏览器中打开开发者选项,切换至【source】选项,然后执行断点调试。

断点调试技巧

在代码调试过程中,最常用的莫过于断点调试,断点调试有很多小技巧,例如断点列表、条件断点、断点调用栈等。

除了基于JavaScript的一些通用基础调试技巧之外,还有一些专门针对React Native的调试技巧。在iOS平台中摇动设备或者使用按组合快捷键【control+command+z】,在Android平台中摇动设备或者使用菜单按钮(在模拟器中使用组合键【command +m】)调出硬件菜单按钮,如图2-36所示。

图2-36 Android、iOS调试

需要注意的是,在测试环境中开发者菜单默认是打开的,开发者可以在测试环境进行相关调试,而在线上环境中开发者菜单会被关闭。

在iOS平台上,打开Xcode中的项目,选择【Roduct】→【Scheme】→【Edit Scheme】,或使用组合键【command+<】。下一步,在左边的菜单中选择【Run】然后将【Build Configuration】改为【Release】。

在Android平台上,默认情况下,由gradle建立发布的开发者菜单将被禁用(例如,gradle的assembleRelease任务)。虽然这种行为可以通过传递给ReactInstanceManager#setUseDeveloperSupport正确的值来自定义。

启动React Native项目,在浏览器中打开一个新的页面:http://localhost:8081/debugger-ui,在Chrome浏览器中打开开发者工具(其他浏览器类似),或者使用快捷键【command + option + i】切换到控制台页面,如图2-37所示。

图2-37 Chrome控制台页面

使用JavaScript调试器,可以很方便地使用浏览器内置的控制台与当前的JavaScript上下文进行交互。在Web开发中,使用JavaScript开发者工具(如React Developer Tools插件)可以查看组件的层次结构、属性和状态,React Developer Tools插件可以在Chrome的扩展程序中安装。当然,在浏览器中也可以调试React Native应用(使用真机调试,确保手机和电脑处于同一个局域网),具体步骤如下。

iOS调试

打开RCTWebSocketExecutor.m文件,将【localhost】改为你电脑的IP地址,然后打开手机或者模拟器在Developer Menu下点击“Debug JS Remotely”选项启动JS远程调试功能。

Android调试

React Native调试Android程序的方式有两种。第一种,通过在【Developer Menu】下的【Dev Settings】中设置你的电脑IP来进行调试;第二种,是命令方式,主要针对Android5.0以上设备,将手机通过USB连接到你的电脑,然后通过adb命令行工具连接手机进行调试,相关命令如下:

adb reverse tcp:8081 tcp:8081

调试面板介绍

Element面板在这个面板中,开发者可以通过Element面板查看整个页面的DOM结构。在调试模式下,还可以查看CSS元素、HTML标签等信息。

Element Inspector命令

利用Element Inspector命令软件开发人员可以很方便地查看React Native界面的层次结构,使用快捷键【command+shift+p】打开终端,输入inspector命令,等待远端连接,如图2-38所示。

图2-38 Inspector调试等待连接

在客户端的APP上打开【Debug JS Remotely】选项重新加载,连接上以后就可以将当前项目的UI层次显示出来,如图2-39所示。

软件代码调试,是软件开发中发现问题的重要手段,当发生程序逻辑问题时,调试可以帮助开发者快速定位问题并解决问题。而通过使用调试工具,不仅可以快速跟踪程序中出现的问题,还能利用工具提供的性能分析功能来提高程序的性能,从而提高应用的体验。

图2-39 Inspector UI层次调试

进行代码调试是提高代码质量的一个重要途径,除此之外,还可以通过代码测试来提高代码的健壮性。常见的代码测试方式有:本地测试、Junit测试、用例测试等。

使用Flow工具进行React Native应用开发不是必须需要掌握的技能,但是掌握了Flow,可以帮助开发者开发出高质量的应用。

Flow是一个静态的类型检查工具,设计之初就是为了可以发现JavaScript脚本里不容易被发现的错误。它依赖类型推断来检查类型错误,甚至可以检测注释代码,利用Flow提供的功能,开发者可以在开发过程中就发现问题从而避免在线上环境出现类似问题。

Flow安装与配置

Flow的安装和配置都比较简单,在项目目录下使用如下命令:

npm install --save-dev flow-bin

然后我们使用命令运行Flow,系统会为我们自动创建一个.flowconfig文件,它配置了Flow的行为,命令如下:

flow check

如果读者在项目中没有发现flowconfig文件,也可以手动新建一个. flowconfig文件,然后在.flowconfig文件中添加如下内容:

.*/node_modules/.*

然后,使用命令再次运行就可以正确地运行程序了。

Jest是一款基于Jasmine的单元测试框架,它提供了侵入式的依赖自动模拟功能,也可以很好地与React测试工具进行整合。Jest是系统默认为我们集成的代码测试框架,如果你的项目比较老,需要手动配置,过程如下。

Jest安装与配置

安装命令如下:

npm install jest-cli –save-dev

然后打开package.json文件,在scripts脚本片段中添加test:

"scripts": {
   …
   "test": "jest"
 }

在React Native源代码的根目录中使用命令npm test来运行jest测试代码,测试代码会放置在_tests_目录下。默认情况下,系统初始化项目的时候,会在 _tests_文件夹下创建index.ios.js和index.android.js两个测试文件专门用来编写测试配置。

当然也可以自己创建测试文件,关于使用Jest进行Javascript进行测试的更多技术细节,读者可以访问Jest的官网:http://facebook.github.io/jest/。

单元测试(Android)

单元测试直接在本地运行,不需要模拟器,React Native使用Buck编译工具来运行测试用例,使用Buck的命令如下:

cd react-native
./scripts/run-android-local-unit-tests.sh

集成测试,又称为组装测试,就是将软件产品中各个模块组装起来,检查其接口是否存在问题,以及组装后的整体功能、性能表现。在开展集成测试之前,往往要先进行深入的单元测试。

集成测试(Android)

集成测试运行在模拟器/真机上,以验证模块、组件以及React Native的内核部分(比如bridge)在端对端测试中是否可以正常运作。在集成测试之前,确保正确安装和配置了Android NDK环境。React Native使用Buck编译工具来运行测试,运行命令如下:

npm install
./scripts/run-android-local-integration-tests.sh

集成测试(iOS)

React Native提供了一些工具来简化跨原生与JS端的组件的集成测试,这套工具的两个主要部分是RCTTestRunner与RCTTestModule。RCTTestRunner预设了React Native的环境,并且以XCTestCase的形式在Xcode中直接运行。而RCTTestModule则以NativeModules.TestModule对象导出到JS环境中。测试代码需要以JS写成,且必须在测试完成后调用TestModule.markTestCompleted()方法,否则测试过程会超时并且失败。失败的表现一般是抛出一个JS异常。

Xcode中运行IntegrationTest和UIExplorer两个官方示例时,可以使用快捷键cmd+U来直接在本地运行集成测试。

快照测试(iOS)

快照测试是集成测试的一种常见测试类型,这类测试首先渲染一个组件,然后使用TestModule.verifySnapshot()来比对屏幕截图与参考效果图的差别。参考效果图是通过在RCTTestRunner中设置recordMode = YES,然后在运行测试时录制的。屏幕截图在32位和64位色深以及不同的操作系统版本上可能会有细微的差别,所以建议强制在指定的配置环境中执行快照测试。

在多人合作的项目开发中,如果某人提交到仓库的代码会影响快照测试,为了不影响原有的测试,那么只需在UIExplorer/UIExplorerSnapshotTests.m中设置_runner.recordMode = YES;,然后重新运行先前失败的测试代码即可。

本章主要从React Native开发环境的搭建、项目运行、项目调试、项目结构,本地代码测试等方面介绍了React Native开发中比较实用的知识和开发技巧,为后面的实战项目的开发打下基础。

下一章将从React Native开发的基础知识着手,一步步深入介绍React Native开发常见的知识点,进而一步步完成实战项目的开发。


相关图书

树莓派开发实战(第3版)
树莓派开发实战(第3版)
React Native移动开发实战 第3版
React Native移动开发实战 第3版
深入浅出React Native
深入浅出React Native
Flutter App开发:从入门到实战
Flutter App开发:从入门到实战
React Native移动开发实战 第2版
React Native移动开发实战 第2版
App自动化测试与框架实战
App自动化测试与框架实战

相关文章

相关课程