weex里native主动发送事件到JS的方案实现

来源:互联网 发布:电话轰炸软件免费版 编辑:程序博客网 时间:2024/06/17 21:15

需求

现在有很多页面需要在返回的时候刷新,比如从购物车跳转到详情页加购,再到购物车,这时候应该刷新页面;如果从订单列表页点击付款跳转后进行支付后,返回的时候刷新数据。

viewappear 和 viewdisappear事件

首先想到的是weex已经提供的绑定到根元素的viewappear 和 viewdisappear事件。使用方法是绑定到根元素上,自定义过component的同学在这里应该不难猜到它是基于fireEvent实现的

  • 1、在Android里,是在onresume里发送viewappear事件,在onpause里发送viewappear。
    接入的时候只要在对应的地方调用对应weexInstance的resume和pause即可:

    public void onResume() {if (wxInstance != null) {  wxInstance.onActivityResume();}}
    public void onPause() { if (wxInstance != null) {    wxInstance.onActivityPause(); }}
  • 2、在iOS里,在viewDidAppear里发送viewappear事件,在viewDidDisappear里发送事件。这里可以参考官方demo的WXDemoViewController实现:
    ```

  • (void)updateInstanceState:(WXState)state {
    if (_instance && _instance.state != state) {

      _instance.state = state;  if (state == WeexInstanceAppear) {      [[WXSDKManager bridgeMgr] fireEvent:_instance.instanceId ref:WX_SDK_ROOT_REF type:@"viewappear" params:nil domChanges:nil];  }  else if (state == WeexInstanceDisappear) {      [[WXSDKManager bridgeMgr] fireEvent:_instance.instanceId ref:WX_SDK_ROOT_REF type:@"viewdisappear" params:nil domChanges:nil];  }

    }
    }
    -(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    [self updateInstanceState:WeexInstanceAppear];
    }

  • (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
    [self updateInstanceState:WeexInstanceDisappear];
    }
    `` 到此,viewappear 和 viewdisappear事件是可以满足以上返回刷新的需求的,只要在vue 里判断:当触发viewappear事件时,如果不是第一次触发,就当做是返回,根据需求,做刷新请求就可以了。`

还没结束

由此想到,如果不仅需要这样的事件,还想给当前页面,从native发其他事件到js,也不基于界面元素,那么该如何办呢?

首先想到的是weex提供的globalEvent,三端都可以发送事件,接收的时候只要注册一下就好了。

var globalEvent = weex.requireModule('globalEvent');globalEvent.addEventListener("geolocation", function (e) {  console.log("get geolocation")});

不过,经过实验会发现,它是全局的,意思是,一个activity/viewcontroller包含多个weex时,只要注册了这个事件,那么就都会收到这个事件。那么一旦我们发送的事件名称出现一样时,就埋了坑,可能出现事件错乱。

这里的解决方案可能会想到规范event name来达到杜绝名称一样的情况,不过这更多是一种治标不治本的办法。

于是乎

于是就有了本文要介绍的方案,让页面传的事件只有自己页面的js处理。

讲道理,这个功能,要是在weex sdk里实现再好不过了。

原理

说来简单,该方案基于globalEvent,携带instanceId,weex里通过比对instanceId,只有一致的情况下才进行处理。

Android:

在渲染weex的fragment/activity的onresume里调用:

resumed:成员变量,默认false

if (resumed) {  Map<String,Object> params = new HashMap<>();  params.put("id", wxInstance.getInstanceId());  wxInstance.fireGlobalEventCallback("resume", params);}resumed = true;

在自定义module里增加接口:

@JSMethod(uiThread = true)public void getInstanceId(final JSCallback callback) {  if (null != callback) {     JSONObject jsonObject = new JSONObject();     jsonObject.put("id", mWXSDKInstance.getInstanceId());     callback.invoke(jsonObject);  }}

iOS:

在渲染weex的viewController里调用:
resumed:成员变量,默认false

-(void)viewDidAppear:(BOOL)animated{    [super viewDidAppear:animated];    if (self.resumed) {        [_instance fireGlobalEvent:@"resume" params:@{@"id": _instance.instanceId}];    }    self.resumed = true;}

在自定义module里增加接口:

-(void)getInstanceId:(WXModuleCallback)callback{    callback(@{@"id": weexInstance.instanceId});}

weex 处理:

weex工程里,封装一个函数,其中shopBase是自定义的module

const shopBase = weex.requireModule('shopBase');export default {  methods: {    /**     * config:     * {     *  event, name of event      *  callback     * }     */    addEventListener(event, callback) {      if(weex.config.env.platform.toLowerCase() !== 'web') {        shopBase.getInstanceId((data) => {            const globalEvent = weex.requireModule('globalEvent');            const id = data.id;            globalEvent.addEventListener(event, function (e) {                if(e.id === id) {                    callback(e);                }            });        })      }    },  },};

在需要的页面调用即可,用法同globalEvent:

addEventListener('resume', function (e) {   shopModal.toast({ message: e.id });});
原创粉丝点击