Weex开发:页面间通信方式

Weex超多大坑,最好别用

白菜普及

Weex 基于当代先进的 Web 开发技术,使用同一套代码来构建 Android、iOS 和 Web 应用。
Weex 的结构是解耦的,渲染引擎与语法层是分开的,也不依赖任何特定的前端框架,目前主要支持 Vue.js 和 Rax 这两个前端框架。Weex 的另一个主要目标是跟进当代先进的 Web 开发和原生开发的技术,使生产力和性能共存。在开发 Weex 页面就像开发普通网页一样;在渲染 Weex 页面时和渲染原生页面一样。

Weex与Native页面之间的通信主要是用module和globalEvent来实现,其中globalEvent可以为通过vue交互来与weex进行通信

一. globalEvent:

globalEvent 用于监听持久性事件,全局事件是需要额外 APIs 处理的次要 API。通过 addEventListener 注册事件监听,当你不再需要的时候,也可以通过 removeEventListener 取消事件监听。

Native端

let testDic = ["key" : "native主动发起广播至weex"]  
 weexInstance.fireGlobalEvent("NativeGlobalEvent", params: testDic)

Vue.js


const globalEvent = weex.requireModule('globalEvent')
export default {
  methods: {
    ......省略N多代码
    addGlobalObserver() {
      globalEvent.addEventListener("NativeGlobalEvent", function (e) {
        modal.alert({
          message: e.key,
        });
      })
    },
    removeGlobalObserver() {
      globalEvent.removeEventListener("NativeGlobalEvent")
    }
  }
}

坑:多次调用addEventListener方法后,无法覆盖回调(函数),会触发多次回调的执行。
exp: Vue.js多次调用addEventListener方法(比如5次),当Native的Weex实例发起fireGlobalEvent时,会直接执行5次函数体的 内的代码块;再此基础上手动调用3次,在native端再进行一次fireGlobalEvent操作,则会累积执行8次函数体内的代码块!但是如果调用removeEventListener,则会把这“八份回调”全部清除。
所以实现通知时候需要额外处理相关的代码逻辑

二.注册Module和callback回调

Native端

  • 创建一个遵循WXModuleProtocol协议的 NSObject 类,并通过宏WX_EXPORT_METHOD将类中定义的方法暴露给Weex,而在native中执行完操作后,可以在设计接口处添加回调,通过block与对应Weex页面进行通信(比如传必要的参数给Weex页面),其中回调block有两种,WXModuleCallback 和 WXModuleKeepAliveCallback

void (^WXModuleCallback)(id result):回调仅执行一次后释放
void (^WXModuleKeepAliveCallback)(id result, BOOL keepAlive):回调一直存在,根据keepAlive的值来决定回调是仅执行一次还是一直保留。注意:回传的result数据可以是任意类型(NSDictionary, NSString, NSArray, Int, Float, Bool),因此要提前与编写Vue的童鞋约定好对应的格式

- (void)showInfoFromWeexKeepAlive:(nullable NSDictionary *)infos keepAliveCallback:(nullable WXModuleKeepAliveCallback)callback {
    
    UIAlertController *alert = [[UIAlertController alloc] init];
    alert.title = @"Native Alert";
    alert.message = infos[@"message"];
    UIAlertAction *action0 = [UIAlertAction actionWithTitle:@"got it" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        callback(@{@"backInfo":@"confirm btn click"},true);
    }];
    
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"cancle" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
        callback(@{@"backInfo":@"cancle btn click"},false);
    }];
    
    [alert addAction:action0];
    [alert addAction:action1];
    
    [UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alert animated:YES completion:nil];
    
   <!- 模拟block keepAlive场景 ->
    callback(@{@"backInfo":@"this is the first callback and keep block alive"},true);
}
  • 然后在Appdelegate方法中初始化完Weex环境后,通过调用 WXSDKEngine 中的 registerModule:withClass方法来注册自己的Module,以便Weex能够识别并使用Native定义的Module
WXSDKEngine.initSDKEnvironment()    
WXSDKEngine.registerModule("YFTest", with: TestWXModule.classForCoder())

vue.js端

  • 通过requireModule引入native定义的module,且需同名
  • 调用module中开放的API执行相关操作
const nativeEvent = weex.requireModule('YFTest')
export default {
  methods: {

    ......省略N多代码
    sendParamToNativeKeepAlive(event) {
      nativeEvent.showInfoFromWeexKeepAlive({"message":"show message from weex"}, function(ret) {

        var str = "";
        str = ret.backInfo;
        modal.confirm({
          message: "weex alert\n" + str,
          okTitle: 'i know'
        })
      });
    }
  }
};

坑:回调函数可能释放也可能一直存在,需要对不同的应用场景进行区分

三、在写vue.js页面的发现在native上很多CSS的样式不支持

  • 简写均不支持,如:margin: 15px 15px 30px 30px;
  • 百分比不支持,如:width: 80%
  • 不能使用嵌套的CSS,布局上只支持flex
  • native上不存在全局样式,使用了预处理器也是不行(查了资料,web是可以有全局样式)
  • ue.js页面使用内置modal模块的toast时,无法屏蔽多次点击操作,需要特殊处理
  • weexView无法使用自动布局,渲染完成的weex页面的frame与weexInstance的frame保持一致

四、页面之间的跳转

  • native -> weex:weex页面需要一个控制器作为容器, 此时就是native间的跳转
  • weex -> weex: 使用weex内置的navigator模块,weex之间传递数据需要用内置模块storage
  • weex -> native: 需要通过module形式通过发送事件到native来实现跳转(参照module的使用)

附:降级方案参考文章

饿了么
飞猪
根据接口配置,接口同时给native提供js文件和h5链接

  • 由后台决定Native使用何种方式加载(Weex | Web)
  • 如果后台指定使用weex,如果渲染失败(包括降级和其他一些会导致渲染失败的原因)则直接移除用来渲染weex页面的view,并改用webView来实现
    坑:如果使用webView来实现,页面之间的通信也就变成了hybrid方式,而不是前面讨论的weex-native之间的module方式
weexInstance.onFailed = { [weak self] (view) in
     //渲染出错,包括降级,需要在这里切换至web展示
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,001评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,210评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,874评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,001评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,022评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,005评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,929评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,742评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,193评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,427评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,583评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,305评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,911评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,564评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,731评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,581评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,478评论 2 352

推荐阅读更多精彩内容