本文基于Weex 0.18.0版本源码
一、什么是Module?
Module 是完成一个操作的方法集合,在 Weex 的页面中,允许开发者 require 引入,调用 module 中的方法,WeexSDK 在启动时候,已经注册了一些内置的 module。
二、Module实现原理
1、所有的Module都需要实现WXModuleProtocol协议,通过WX_EXPORT_METHOD、WX_EXPORT_METHOD_SYNC导出方法给JS调用。
WX_EXPORT_METHOD和WX_EXPORT_METHOD_SYNC的区别是后者是同步调用,前者支持异步调用。
2、Native通过WXSDKEngine类方法+ (void)registerModule:(NSString*)name withClass:(Class)clazz注册Module。以剪贴板模块为例,Native通过代码[self registerModule:@"clipboard" withClass:NSClassFromString(@"WXClipboardModule")] 注册; Weex页面通过代码const clipboard = weex.requireModule('clipboard')引入clipboard模块,通过clipboard对象调用Native暴露给JS的方法setString和getString。
3、Native如何注册Module?
WXSDKEngine类registerModule实现细节
如上代码,注册模块的实际工作交给了WXModuleFactory,WXModuleFactory维护了一个模块名到WXModuleConfig的字典,WXModuleConfig类通过registerMethods遍历模块类导出给JS调用的方法并保存在字典asyncMethods、syncMethods中;[[WXSDKManager bridgeMgr] registerModules:dict]通过调用JS方法registerModules在JS生成跟所有模块的导出方法同名的方法,以便后续JS调用。
WXModuleFactory _registerMethods代码如下:
WXBridgeContext registerModules代码如下:
4、JS如何调用Module导出的方法?
在初始化JS引擎时,WXBridgeContext通过调用registerGlobalFunctions在JSContext里面注册了callNativeModule给JS调用,如下:
JS调用Native时会把instanceId(WXSDKInstance id)、moduleName(模块名)、methodName(方法名)、arguments(方法)、options(额外参数)传进来,最终通过WXModuleMethod的invoke方法从WXModuleFactory查找对应的模块类和方法进行调用,而invoke方法最终通过NSInvocation invoke方法来进行调用。