前言->React Native与传统的HybirdApp最大的区别就是抛开WebView,使用JSC+原生组件的方式进行渲染
整体框架
React与React Native的原理是相同的,都是由JavaScript实现的虚拟DOM来驱动页面View的渲染,只不过React.js驱动HTML DOM的渲染,RN是驱动iOS、Android原生组件的渲染
前端页面开发及渲染
- 准备阶段由原来承担大部分工作,包括启动JS运行环境,创建空白画布,实例化自定义module及导出各种可控JS使用的API等。
- 渲染阶段的主要职责包括根据注册信息创建实际视图、维护虚拟dom树、维护待渲染队列及对布局样式进行转换等。
(1)JS入口
- 将当期APP的对象注册到AppRegistry组件中,AppRegistry组件是js moudle。 ```javascript import { AppRegistry } from “react-native”; import App from “./src/index”;
AppRegistry.registerComponent(“Wubacst”, () => App);
<a name="BQXEx"></a>
### (2)RN AppRegistry
- **AppRegistry 是运行所有React Native应用程序的js入口点**
- **应用程序跟组件需要通过AppRegistry.registerComponent来注册他们自身**
- **然后本地系统就可以加载应用程序的包,再然后当AppRegistry.runApplication准备就绪后就可以真正的运行该应用程序了**
- **AppRegistry在require序列里是required,确保在其他模块被需求之前js执行环境已经被required**
```javascript
//static静态方法,用来注册配置信息
static **registerConfig**(config: Array<AppConfig>)
//static静态方法,注册组件
static **registerComponent**(appKey: string, getComponentFunc: Function)
//static静态方法,注册线程
static **registerRunnable**(appKey: string, func: Function)
//static静态方法,进行运行应用
static **runApplication**(appKey: string, appParameters: any)
runApplication: function runApplication(appKey, appParameters) {
var msg = 'Running application "' + appKey + '" with appParams: ' + JSON.stringify(appParameters) + '. ' + '__DEV__ === ' + String(__DEV__) + ', development-level warning are ' + (__DEV__ ? 'ON' : 'OFF') + ', performance optimizations are ' + (__DEV__ ? 'OFF' : 'ON');
infoLog(msg);
BugReporting.addSource('AppRegistry.runApplication' + runCount++, function () {
return msg;
});
invariant(runnables[appKey] && runnables[appKey].run, 'Application ' + appKey + ' has not been registered.\n\n' + "Hint: This error often happens when you're running the packager " + '(local dev server) from a wrong folder. For example you have ' + 'multiple apps and the packager is still running for the app you ' + 'were working on before.\nIf this is the case, simply kill the old ' + 'packager instance (e.g. close the packager terminal window) ' + 'and start the packager in the correct app folder (e.g. cd into app ' + "folder and run 'npm start').\n\n" + 'This error can also happen due to a require() error during ' + 'initialization or failure to call AppReg
istry.registerComponent.\n\n');
SceneTracker.setActiveScene({
name: appKey
});
runnables[appKey].run(appParameters);
}
(3)ReactDOM.render
ReactDOM.render是React的最基本方法用于将模板转为HTML语言,并插入指定的DOM节点
ReactDOM.render(
<Page />,
document.getElementById('app')
);
(4)RN组件的生命周期
像Android和iOS开发一样,React Native中的组件也有生命周期
- 当应用启动时,React Native在内存中维护着一个虚拟DOM,组件的生命周期就是指组件初始化并挂载到虚拟DOM为开始,到组件从虚拟DOM卸载为终结。生命周期的方法就是组件在虚拟DOM中不同状态的描述。
- 组件的生命周期分为三个阶段:
- 挂载
- 更新
- 卸载
—>挂载
挂载指的是组件的实例被创建并插入到DOM中,调用方法:
constructor(props) {
super(props);
this.state = {
text: '构造方法'
};
}
constructor是RN组件的构造方法,它在RN组件被加载前先被调用。当我们的组件继承自React.Component时,需要在构造方法中最先调用super(props)。如果不需要初始化state,则不需要实现构造方法。
- ComponentWillMount方法在挂载前被立即调用。它在render方法前被执行,因此,在ComponentWillMount方法中设置state并不会导致重新被渲染。它只执行一次渲染,render方法中不应该修改组件的props和state,render方法在更新阶段也会被调用,前提是shouldComponentUpdate 方法返回true。
ComponentDidMount方法在组件被挂载后立即调用,在render方法后执行,可以在这个方法中获取其中的元素或者子组件,需要注意的是,子组件ComponentDidMount方法会在父组件的ComponentDidMount方法之前调用,如果需要从网络加载数据显示到界面上,最好在这里进行网络请求。在ComponentDidMount方法中设置state将被重新渲染。
—>组件更新
—>卸载
-
(5)React Native如何把React转化为元素的API
- React Native会在一开始生成OC模块表,然后把这个模块表传入JS中,JS参照模块表,就能间接调用OC代码。
相当于买了一个机器人(OC),对应一份说明书(模块表),用户(JS)参数说明书去执行机器人的操作
(6)React Native如何做到JS与OC交互
iOS原生API有个JavaScriptCore框架,通过它就能实现JS和OC交互
- 首先写好前端的jsx代码
- 把jsx代码解析成JavaScript代码
- OC读取JS文件
- 把JavaScript读取出来,利用JavaScriptCore执行
- JavaScript代码返回一个数组,数组中会描述OC对象,OC对象的属性,OC对象所需要执行的方法,这样就能让这个对象设置属性,并且调用方法
(7)RN通信机制
- OC生成一张模块配置表,包含所有模块和模块里的方法,根据特定的标识宏(RCT_EXPORT_MODULE()),将可以暴露的方法暴露给JS。
- OC-JS交互流程