前言

在移动应用开发中,组件化可以提高代码的模块化和重用性,降低耦合度。当下大部分APP都至少包含一到两种Hybrid框架,H5基本是必要的,还可能叠加React Natvie、Weex或Flutter。

对于Hybird来说,Native的很多能力是其不具备的,需要通过各自的 Bridge / Plugin 来实现功能扩展,经过长时间的迭代后会产生大量的API。API的组件化可以让不同Hybrid平台甚至不同的APP使用同一份组件代码,抹平了跨平台以及跨应用的API实现差异,降低了API与工程的耦合度,同时也有利于API的统一管理,降低维护成本。

一、组件分类

将属性相同的API归为同一个组件。

基于OC端的Bridge-API组件化应用

二、组件设计

1、制定API参数标准

1)入参规范

{
    "pluginName": "http",  // 组件名
    "methodName": "dataRequest",  // 接口名
    "parameter": {  // 入参数
        "url": "https://domain/path/api.json",
        "method": "POST",
        "params":"{\"operation\":\"on\"}",
        "content-Type": "application/json"
    },
    "callBackName": "callback_9d12ef83c2b245d7"  // JS回调方法
}

 2)出参规范

{
    "code": "0",  // 错误码
    "message": "success",  // 信息
    "keepAlive": 0  // 是否保留回调方法
    "data": {}  // 返回数据
}

2、组件抽象类的定义

基于OC端的Bridge-API组件化应用

3、组件API的调用流程

基于OC端的Bridge-API组件化应用

三、基础建设

1)HybridComponent:组件基类

@protocol HybridComponent <NSObject>
@required
+ (NSString *)getName;
@optional
- (NSDictionary *)methodsTestData;
- (void)onReady;
- (void)onUnload;
@end

 2)HybridDataFormat:通用错误码定义、出参格式化工具

typedef NS_ENUM(NSInteger, HybridErrorCode){
    HybridErrorCodeSuccess            = 0,     // 成功
    HybridErrorCodePluginotExist      = 100001, // 组件不存在
    HybridErrorCodeMethodNotExist     = 100002, // 组件方法不存在
    HybridErrorCodeParamException     = 100003, // 参数异常
};
@interface HybridDataFormat : NSObject
+ (NSDictionary *)JSONObjectWithCode:(NSInteger)code message:(NSString *)message;
+ (NSDictionary *)JSONObjectWithCode:(NSInteger)code message:(NSString *)message keepAlive:(BOOL)keepAlive;
+ (NSDictionary *)JSONObjectWithData:(id)data code:(NSInteger)code message:(NSString *)message;
+ (NSDictionary *)JSONObjectWithData:(id)data code:(NSInteger)code message:(NSString *)message keepAlive:(BOOL)keepAlive;
@end

 3)HybridPluginProtocol:Hybrid容器代理方法

@protocol HybridPluginProtocol <NSObject>
#pragma mark - 前端回调 -
- (void)callbackName:(NSString *)callbackName params:(NSDictionary *)params;
#pragma mark - 容器能力 -
/// 设置NavigationBar属性 - { bgColor、bgImageName }
- (void)setNavigationBarPropertys:(NSDictionary *)propertys;
. . .
@end

4)HybridInvokeModel:入参模型(params 、source、Hybrid容器代理、calBack)

5)HybridPluginManager:组件注册、组件注销、API参数配置

6)HybridPluginExecutor:执行API的分发,实现API到组件的具体方法桥接

四、实际应用

1、OC端的组件封装

1)新建Class,继承于HybridComponent

#import "HybridComponent.h"
@interface HybridHttp : HybridComponent
@end

2) 组件注册 + API实现

#import "HybridHttp.h"
@implementation HybridHttp
#pragma mark - 组件注册 -
+ (void)load { 
    [[HybridPluginManager sharedInstance] regsiterImpClass:[self class]]; 
}
#pragma mark - 组件名称 -
+ (NSString *)getName {
    return @"http";
}
#pragma mark - API测试数据 - 
- (NSDictionary)methodsTestData {
    return @{ @"core.http.dataRequest": @{@"url": @"https://domain/path/api.json"} };
} 
#pragma mark - method - 
METHOD_CHAIN_MOUNT(http, dataRequest)
- (void)dataRequest:(HybridInvokeModel *)invokeModel {
    // do something and callback
    . . .
    if (invokeModel.callBack) {
        invokeModel.callBack([HybridDataFormat JSONObjectWithData:@{@"key": @"value"} code:HybridErrorCodeSuccess message:@"success"]);
    }
}
#pragma mark - 生命周期 -
- (void)onReady { }
- (void)onUnload { }
@end

2、Web端的API调用

1)上层API的调用方式

function dataRequest() {
    core.http.dataReqeust(parameter: @{url: 'https://domain/path/api.json'},
    callback: (result) => {
        if(result.code) {
            console.log(result.message)
        }   
    })
}

2)底层API的具体实现(JSBridge参数转换、callback方法挂载)

function dataRequest() {
    let apiParams = {url: 'https://domain/path/api.json'}
    let invokeParams = {pluginName: 'http', methodName: 'dataRequest', parameter: JSON.stringify(apiParams), callBackName: 'callback_9d12ef83c2b245d7'}
    window.webkit.messageHandlers.core.postMessage({fuctionName: 'invokeAPI', parameter: JSON.stringify(invokeParams)})
}

发表回复