前言
用React Native开发有一段时间了,想写一下有关的资料以便自己查阅,一下内容均来自于网络,如有侵犯联系我删除。
是Facebook发布的,可以让广大开发者使用JavaScript和React开发应用,提倡组件化开发,也就是说React Native提供了一个个封装好的组件让开发者来进行使用,甚至可以相关嵌套形成新的组件。
使用React Native开发者可以维护多种平台(Web,Android和IOS)的同一份业务逻辑核心代码来创建原生应用。
现阶段Web APP的的体验还是无法达到Native APP的体验,所以这边fackbook更加强调的是“learn once, write everywhere”,应用前端我们使用js和React来开发不同平台的UI,下层核心模块编写复用的业务逻辑代码,提供应用开发效率。
React Native的设计理念:既拥有Native的用户体验、又保留React的开发效率。
React Native背景
- React 是由Facebook推出的一个JavaScript框架,主要用于前端开发。
- React 采用组件化方式简化Web开发
- DOM:每个HTML界面可以看做一个DOM
- 原生的web开发方式,HTML一个文件,javaScript一个文件,文件分开,就会导致修改起来比较麻烦。
- 可以把一组相关的HTML标签和JavaScript单独封装到一个组件类中,便于复用,方便开发。
- React 可以高效的绘制界面
- 原生的Web,刷新界面(DOM),需要把整个界面刷新.
- React只会刷新部分界面,不会整个界面刷新。
- 因为React独创了Virtual DOM机制。Virtual DOM是一个存在于内存中的JavaScript对象,它与DOM是一一对应的关系,当界面发送变化时,React会利用DOM Diff算法,把有变化的DOM进行刷新.
- React是采用JSX语法,一种JS语法糖,方便快速开发。
常见的五种App开发模式
Native App
- Native App:指使用原生API开发App,比如iOS用OC语言开发
- 优点:性能高
- 缺点:开发维护成本高,养一个原生开发工程师需要很多钱,最重要iOS版本更新也成问题。
Web App
- Web App:指使用Html开发的移动端网页App,类似微信小程序,整个App都是网页。
- 优点:用户不需要安装,不会占用手机内存
- 缺点:用户体验不好,不能离线,必须联网
Hybrid App(Cordova)
- Hybrid App:混合开发模式,原生Api+Html共同开发,比如iOS,用html写好界面,用UIWebView展示。
- 优点:界面复用性强,一个界面,iOS和安卓都可以使用
- 缺点:相对于原生,性能相对有所损害
Weex
- Weex:基于Vue(JS框架)的语法开发的App,底层会自动把JS代码解析成对应平台(iOS,安卓)的原生API,本质还是原生API开发,只不过表面是用Vue开发。
- 优点:可以做到一套代码,跨平台执行,底层会自动判断当前是哪个平台,转换为对应平台的原生API代码。
- 缺点:开源较晚,互联网上相关资料还比较少,社区规模较小
React Native
- React Native:基于React开发的App
- 优点:跳过App Store审核,远程更新代码,提高迭代频率和效率,既有Native的体验,又保留React的开发效率。
- 缺点:对于不熟悉前端开发的人员上手比较慢,不能真正意义上做到跨平台,使用后,对app体积增加。
- 相信大多数人了解完React Native,越来越困惑了,那不是跟Native冲突了吗,Native是用原生Api开发,但是React Native又是用React开发。
框架简介
- React:不同平台上编写基于React的代码,“Learn once, write anywhere”。
- Virtual DOM:相对Browser环境下的DOM(文档对象模型)而言,Virtual DOM是DOM在内存中的一种轻量级表达方式(原话是lightweight representation of the document),可以通过不同的渲染引擎生成不同平台下的UI,JS和Native之间通过Bridge通信。
- iOS/Android。(Web得通过React Web)
线程模型
React Native应用中存在三个线程队列,它们工作的流程大概如下:UI Event Queue触发事件,通过Bridge调用JS代码在JS Event Queue中运行,JS运行后将视图更新分发给Native Module Event Queue中的线程,Native Module Event Queue负责计算,然后将最后的结果交给UI Event Queue中的线程去更新。 其中UI Event Queue为主线程。
JavaScript对象和原生代码交互
下图以JavaScript与Objective-C交互为例,大致描述交互过程。
1.JS端调用某个OC模块暴露出来的方法。
2.把上一步的调用分解为ModuleName,MethodName,arguments,再扔给MessageQueue处理。
在初始化时模块配置表上的每一个模块都生成了对应的remoteModule对象,对象里也生成了跟模块配置表里一一对应的方法,这些方法里可以拿到自身的模块名,方法名,并对callback进行一些处理,再移交给MessageQueue。具体实现在BatchedBridgeFactory.js的_createBridgedModule里,整个实现区区24行代码,感受下JS的魔力吧。
3.在这一步把JS的callback函数缓存在MessageQueue的一个成员变量里,用CallbackID代表callback。在通过保存在MessageQueue的模块配置表把上一步传进来的ModuleName和MethodName转为ModuleID和MethodID。
4.把上述步骤得到的ModuleID,MethodId,CallbackID和其他参数argus传给OC。至于具体是怎么传的,后面再说。
5.OC接收到消息,通过模块配置表拿到对应的模块和方法。
实际上模块配置表已经经过处理了,跟JS一样,在初始化时OC也对模块配置表上的每一个模块生成了对应的实例并缓存起来,模块上的每一个方法也都生成了对应的RCTModuleMethod对象,这里通过ModuleID和MethodID取到对应的Module实例和RCTModuleMethod实例进行调用。具体实现在_handleRequestNumber:moduleID:methodID:params:。
6.RCTModuleMethod对JS传过来的每一个参数进行处理。
RCTModuleMethod可以拿到OC要调用的目标方法的每个参数类型,处理JS类型到目标类型的转换,所有JS传过来的数字都是NSNumber,这里会转成对应的int/long/double等类型,更重要的是会为block类型参数的生成一个block。
例如-(void)select:(int)index response:(RCTResponseSenderBlock)callback 这个方法,拿到两个参数的类型为int,block,JS传过来的两个参数类型是NSNumber,NSString(CallbackID),这时会把NSNumber转为int,NSString(CallbackID)转为一个block,block的内容是把回调的值和CallbackID传回给JS。
这些参数组装完毕后,通过NSInvocation动态调用相应的OC模块方法。
7.OC模块方法调用完,执行block回调。
8.调用到第6步说明的RCTModuleMethod生成的block。
9.block里带着CallbackID和block传过来的参数去调JS里MessageQueue的方法invokeCallbackAndReturnFlushedQueue。
10.MessageQueue通过CallbackID找到相应的JS callback方法。
11.调用callback方法,并把OC带过来的参数一起传过去,完成回调。
整个流程就是这样,简单概括下,差不多就是:JS函数调用转ModuleID/MethodID -> callback转CallbackID -> OC根据ID拿到方法 -> 处理参数 -> 调用OC方法 -> 回调CallbackID -> JS通过CallbackID拿到callback执行
JavaScript和本地代码间的通信
其中通信的特点是:
- 异步的
- 序列化的
- 批量的,对于大批量的通信事件可以将其分成几部分,减少时间延迟
异步执行
在Javascript代码和原生平台之间的所有操作都是异步执行的,并且原生模块还可以根据需要创建新的线程。这意味着你可以在主线程解码图片,然后在后台将它保存到磁盘,或者在不阻塞UI的情况下计算文字大小和界面布局等等。所以React Native开发的app天然具备流畅和反应灵敏的优势。Javascript和原生代码之间的通讯是完全可序列化的,这使得我们可以借助Chrome开发者工具去调试应用,而不论应用运行在模拟器还是真机上。
拓展性
使用React Native,无需编写一行原生代码即可创造一款不错的app。尽管如此,使用自定义的原生视图和模块来扩展React Native也非常容易 —— 这意味着你现有的所有工作都可以被复用,你喜欢的各种原生库都可以被导入。