专注于
IT技术和业内交流

剖析React Native

提起React Native的移动开发者想的比较多的估计是Facebook的那句:“learn once, write everywhere”。

一、React Native 是什么?

首先,react native 到底是个什么东东:它是Facebook开源的一套框架,其目的在于使用JavaScript语言编写iOS native的控件。更直白的讲就是,你用JS(JavaScript,下同)写的代码通过react-native lib桥接到Xcode中写的标准iOS程序中。在JS程序中,开发者可以使用react native定义的一套和cocoa touch中UI控件类等价的类,来完成UI层的开发工作,Xcode 编译器 会利用 react-native lib将JS写的代码编译成iOS原生的UI组件,下图展示了利用Xcode的视图调试功能展示了JS代码编译的结果,可以看到,这些JS语言最终确实是被编译成了UIView等对象,而不是H5界面经常使用的webview,有了这个认识之后,我们对react native就不在那么陌生了。 

二、 React Native 技术构成

1基本构成元素

1.React Native 的库同时包含了OC代码和javascript 代码,由这两种代码共同提供了一套用于构建界面UI系统的元素,包括但不限于:
2.OC传统UI组件;
3.OC上的手势识别及事件响应系统(如TouchableHighlight);
4.基于流的布局系统;
5.翻阅Facebook官网上的API文档,可以发现它基本上是实现了Cocoa Touch 框架上的最常用的UI控件:
剖析React Native
6.基本上我们用JS写代码也是使用这些基本组件来构建我们的UI界面的。除此之外,你也可以在OC中,定制自己的模块,通过桥接的方式来在React Native 中使用。

2.React Native 中的事件响应系统

本地APP 和web 端的最大区别就是本地APP有着完美的事件响应系统,用户能够获得更好的用户体验。在React Native中也提供了一套事件响应系统,扒一扒React Native 的源码(在 ResponderEventPlugin.js 文件中),能够窥到React native事件响应的基本流程: 
剖析React Native
可见React native的响应系统和Cocoa touch类似,一个view如果想要对事件作出响应,它只需要实现函数:
1.View.props.onStartShouldSetResponder: (evt) => true, -当前view是否想作为touch 的响应者?
2.View.props.onMoveShouldSetResponder: (evt) => true, -当前view是否想作为move 事件 的响应者?
如果返回true,尝试要变成第一响应者,那么下面两个函数中的一个会被调用:
3.View.props.onResponderGrant: (evt) => {} -当前view是第一响应者,在这里展示响应的交互效果(如背景色变化等)和事件触发的其他逻辑;
4.View.props.onResponderReject: (evt) => {} – 其他view是第一响应者;
5.考虑到响应系统的复杂性,React Native 在对事件响应封装的基础上实现了一些抽象类,如类似Cocoa Touch 中UIButton 的 TouchbleHighlight,你可以向使用view一样将它放到你希望有交互效果的地方。我们通过下图来看看如何使用TouchbleHighlight:
剖析React Native

三、React Native UI更新逻辑

在Cocoa Touch 系统中,UI更新是典型的MVC模式:Controller 通过数据的变更,来更新view层的展示,但在React Native 中却大相径庭:React Native 通过状态机的机制来驱动整个view层的更新。在开始介绍这一块之前不得不得先说一下React Native 的渲染方式:
从之前图片中给出的代码片段中读者也能窥出这种构建页面的方法和HTML语言很像:通过标签系统构建出分层的页面逻辑(父子关系),布局代码则采用CSS 的方式通过单独的代码来控制,这样显示的将业务逻辑和布局逻辑分开,使得整个代码层次逻辑更清晰。
在React Native中,整个UI都是一个component树:前面我们提到的ListView等UI组建都是一种具体的component,React Native通过将component树编译成一个virtual-DOM:虚拟文档对象模型,熟悉HTML的读者可能对于这个DOM非常熟悉,没错,就是那个DOM,整个的UI的关系可以通过这个virtual-DOM很清晰的体现,而且更重要的是,React Native的UI更新逻辑也是依赖于这个树来实现的:我们知道,笼统的讲,一个页面的更新,肯定是由数据的变更来驱动的,比如网络数据的更新或者是用户触摸导致的touch事件的发生(以及后续业务逻辑的跟进),那么如何将这些数据的变更和界面的刷新相绑定呢?如何知道哪一块的数据变更后需要刷新哪一块的UI呢?要知道每次数据更新都重绘整个界面实在是一个吃力不讨好的事情:不仅你的APP处于一种高负载运行状态,而且用户体验也不好。React Native很巧妙的通过用户提供的state变量维着一个状态机,通过将这个状态机来驱动virtual DOM树的UI更新,如下图所示:
剖析React Native

设计好了state信息之后,React Native会根据代码逻辑计算出那一块的DOM组件需要进行更新,整个过程不需要开发者来主动的干预,开发者只需要建立好state系统,并根据数据变化来维护state信息即可,React Native会在后台为你做好这一切。
那么一个component 中的state 是什么呢?其实就是一个属性,比如一个bool值或者数组或者任何其他JS支持的类型。一个component对象其实是包含了两种类型的属性的:property和state,前者主要是一些固定值的属性,后者则是那些数据会发生变化,并且这种变化会导致界面某一部分重绘的属性,比如列表页里面的数据源等,如何区分一个属性是应该被归类为property还是state,Facebook 的 React 官网文档:think in react上有详细的介绍,这里就不再赘述。

四、React Native的通信机制

在讲诉具体的通信原理之前,我们首先来看一下,在代码实现上是怎样的。我们这里说的通信,很大程度上指的是我们用javascript写的模块和OC写的本地模块直接能否互相调用,如下图所示: 
剖析React Native
在具体深入细节之前,先想一下在纯OC代码中,如果一个类对象想直调用另一个类对象的简单情况,那么主调用模块必须要知道的是:
1.被调用模块的地址在哪儿?
2.被调用模块的方法名是什么?
3.需要传入哪些参数进去?
4.也即一个完整的可执行的调用地址必须有三个单元组成:(模块地址、方法名、参数),这三者缺一不可,这些信息的获得主要通过头文件机制和Cocoa Touch 运行时系统来提供。而React Native的通信原理也是如此:
5.我们可以将React Native里用JS代码写的模块和OC写的本地模块看作是两个互相陌生的城市,那么很显然,这两个城市之间的人要想有效的沟通,必须要彼此有一张对方城市的地图才行。那么在React Native世界里,这两张地图就是模块配置表,它看上去大概是酱紫滴(一下部分资料来源于Bang’s blog):

{
    "remoteModuleConfig":{
            "RCTSQLManager":{
                    "methods":{
                        "query":{
                                "type":"remote",
                                "methodID":0
                    }
},
 "moduleID":4
 },

未经允许,不得转载本站任何文章:代码山 » 剖析React Native

分享到:更多 ()

专注品牌化高端网站建设

商务服务联系我们