背景:
由于公司的RN库版本是0.4.x,调研后决定升级到0.6.x。之前没有接触过RN,在上手之前,现在网上大约进行一下基础知识的学习,并将总结性的结论一致放在这里,便利以后查阅。
参阅:
ReactNative iOS 框架源码解析
【React Native】从源码一步一步解析它的完结原理
ReactNative源码解析——通讯机制详解(1/2)
ReactNative源码解析——通讯机制详解(2/2)
ReactNative源码解析——烘托机制详解
全体架构、流程
- 首先写好JSX代码(React框架便是运用JSX语法)
- 把JSX代码解析成javaScript代码
- OC读取JS文件
- 把javaScript代码读取出来,利用JavaScriptCore履行
- javaScript代码返回一个数组,数组中会描述OC目标,OC目标的特点,OC目标所需求履行的办法,这样就能让这个目标设置特点,而且调用办法。
- 如果你了解这些东西的实质其实就很清楚了。动态或许脚本言语要跟本地言语互通要具备如下几点:
- 本地言语有一个runtime机制来对目标的办法调用进行动态解析。
- 本地言语一定有一个脚本的解析引擎
- 树立一个脚本言语到本地言语的映射表,KEY是脚本言语知道的符号,VALUE是本地言语知道的符号。经过这个映射表来构建从脚本到本地的调用。
- 经过上述3个准则,无论是RN, JSPATCH, WEEKS, WEX都是运用同样的机制。。没有什么神秘可言,也没有什么复杂度可言了。。。
发动流程
React Native发动流程(iOS)
React Native加载JS源码流程(iOS)
烘托原理
通讯机制
ReactNative 的初始化
native module 注册
- 要将 Native module(类、接口)曝露给 JS,module需求完结
RCTBridgeModule
协议,而且在完结中要刺进RCT_EXPORT_MODULE
宏。具体曝露的办法也需求经过RCT_EXPORT_METHOD
宏定义。 -
RCT_EXPORT_MODULE
的源码:RCT_EXTERN void RCTRegisterModule(Class); +(NSString *)moduleName { return @ #js_name; } +(void)load { RCTRegisterModule(self); }
- 经过上图流程,native module注册最终定位到
RCTCxxBridge._initModulesWithDispatchGroup
:- (void)_initModulesWithDispatchGroup:(dispatch_group_t)dispatchGroup { NSMutableArray<Class> *moduleClassesByID = [NSMutableArray new]; NSMutableArray<RCTModuleData *> *moduleDataByID = [NSMutableArray new]; NSMutableDictionary<NSString *, RCTModuleData *> *moduleDataByName = [NSMutableDictionary new]; // Set up moduleData for automatically-exported modules for (Class moduleClass in RCTGetModuleClasses()) { NSString *moduleName = RCTBridgeModuleNameForClass(moduleClass); moduleData = [[RCTModuleData alloc] initWithModuleClass:moduleClass bridge:self]; moduleDataByName[moduleName] = moduleData; [moduleClassesByID addObject:moduleClass]; [moduleDataByID addObject:moduleData]; } // Store modules _moduleDataByID = [moduleDataByID copy]; _moduleDataByName = [moduleDataByName copy]; _moduleClassesByID = [moduleClassesByID copy]; }
- 上述代码第
8
行RCTGetModuleClasses()
即是获取经过RCTRegisterModule
注册的 module 类(即一切曝露给 JS 的类) - 至此,一切需求曝露给 JS 的 module 都已注册完结,并以
RCTModuleData
格式存储在RCTCxxBridge
中。 - 大部分 module 都是
懒加载
,只有那些需求在主线程完结初始化以及有常量需求导出的 module才会在注册时实例化。
JS 获取 native module 信息
- 收集了一切曝露给 JS 的 module(也可称之为生成了一份 native module 注册表);
- 在 JS Context 中设置了
nativeModuleProxy
以及nativeFlushQueueImmediate
; - 初始化了相关的类,如:
NativeToJsBridge
、JsToNativeBridge
以及JSCExecutor
等
JS 调用 native module
- NativeModules.moduleName — 该过程主要是获取 native module 的信息(moduleID、methodID),最终封装为 JS object ({methodName: fn});
- NativeModules.moduleName.methodName(params) — 履行调用。
总结
- RN 项目中涉及多种言语,但 Native 与 JS 的通讯发生在
C++
与JavaScript
间; - 双方具体担任通讯的分别是:Native 的
JSCExecutor
与 JS 的MessageQueue
; - 在 Native 侧保护了一份曝露给 JS 的 module 注册表,在 JS 侧保护了一份曝露给 Native 的 module 注册表;
- RN 中 Native to JS 的通讯没有运用
JavaScriptCore
提供的机制(block
、JSExport
),而是自己完结了一套跨渠道通讯机制。