Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

「前端」weex页面传参 #34

Open
fromIRIS opened this issue Aug 13, 2017 · 2 comments
Open

「前端」weex页面传参 #34

fromIRIS opened this issue Aug 13, 2017 · 2 comments
Labels

Comments

@fromIRIS
Copy link

本文来自尚妆前端团队南洋

发表于尚妆github博客,欢迎订阅!

前言

我司在weex上的应用是保证三端统一,为了延续web开发体验,统一在三端的跳转都采用url的形式,即采用<a>组件,或者自定义的openUrl方法进行跳转。

假如现在点击B按钮跳转到/b.html页面,在vue文件中统一书写openUrl('/b.html')。H5中就是简单的调用window.location.href = /b.html,在native中会打开一个视图,然后去下载跟/b.html对应的b.min.jsjs文件,进行原生视图渲染。页面与js文件的映射关系以及如何维护可以翻阅之前的文章查看App的跳转规则的weex支持方案设计。

统一采用url跳转的方式进行页面跳转,为了传参方便,我们也统一采用在url后拼接参数的形式进行页面间传参。

正向传参

不管是weex(native)还是weex(H5)都是通过页面的url进行跳转。

假设案例:

x.com/a.html跳转到x.com/b.html?age=12

1)weex(native) > weex(native) 实例化时从url中取得参数并传入到实例中

weex文档中写到

每个 Weex 页面都有被创建、被销毁两个必经阶段,同时在 Weex 页面运行过程中,native 有机会主动向 Weex 页面发送消息。
Native 有机会在创建一个 Weex 页面的时候,传入一份外部数据,JS 框架也有机会借此机会为相同的 JS bundle 配合不同的 data 生成不同的页面内容。

由上可知native在渲染一个weex页面的时候有机会往这个weex页面传入一个Object类型的数据,数据能通过weex.config取得。

在我司的设计中,native首先会截取跳转的url,然后截取下参数,再把参数传入到weex实例中去。这样我们就能通过weex.config.age进行数据的获取,从而渲染不同的页面内容。

[_instance renderWithURL:[NSURL URLWithString:mstrURL] options:[self SHWeexOptionsWithH5URL:mstrH5URL withURL:mstrURL] data:nil];

2)weex(web)> weex(web)在weex-vue-render层面从url读取参数,写入weex.config

native实现这上述讲到的方式进行数据传递,那么web端也要以相同的方式weex.config.age这种方式去取得页面中的参数age。

本司web端的weex依赖文件是通过webpack打包的方式,所以在requireweex-vue-render依赖后,获取当前url的参数,再存进weex.config对象就好了。

require('weex-vue-render')

// hack 将页面url的参数写入到weex.config中
// app已经有这样的方法,h5自己实现
let urlParamObj = {};
try {
  urlParamObj = utils.parseUrl(window.location.search.slice(1), '&', "=", {maxKeys: 0});  
} catch (error) {
  console.log('--------------weex.js parseUrl---------------------');
  console.log(error);
  console.log('------------------------------------');
}


for (let key in urlParamObj) {
  window.weex.config[key] = encodeURIComponent(urlParamObj[key]);
}

3)native > weex(native) 同理
4)native > weex(web) 同理

对于3、4两种情况,native跳转weex,不管是跳到weex(native)还是跳转到weex(web),都是使用url的形式进行跳转。例:x.com/b.html?age=12。上面也讲到了在weex页面native和web如如何将参数写入weex.config对象中去的。要取得参数,统一在vue中编写weex.config.age便能取得传递进来的age参数。

至此我们统一了三端(ios、android、H5)从A页面到B页面正向的传参方式。

反向传参

1)weexA(native) > weexB(native),weexB页面选择完毕返回weexA页面, weexB(native) > weexA(native)

在提交订单页面我们可以选择优惠券,进入到优惠券使用页面,首先会进行正向传参,因为选择优惠券页面会使用提交订单页的订单数据。

然后在选择优惠券页面选择任意优惠券会回到提交订单页,这时需要携带优惠券数据回去,我们称这个为反向传参。

查看官网我们本可以使用BroadcastChannel这个api去做实例间的数据传递,但是在vue的JS Framework中还不支持这个特性,所以我们暂时使用的是globalEvent这个实例级别的api去代替应用级别的数据传递。

我们首先在公司内部集成的module中增加了fireGlobalEvent方法,在选择优惠券页面调用这个方法。

fireGlobalEvent('getConpon', {
    id: '3323',
  }, function () {
  if (web) {
      
  } else {
    navigator.pop()
  }
})

这个方法首先注册了getCoupon事件,然后传递了数据对象

{
    id: '3323'
}

最后注册了一个回调,当前页面会执行这个回调,回退上一页。

而在上一页(提交订单页),注册了一个事件监听,当这个事件名被触发了,就接收来自这个事件的数据。

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

这是业务逻辑中的实现,我们再来看看native为了达到返回上一页并传参效果做了什么处理(android为例)。

public void fireGlobalEvent(String name, String data, final JSCallback callback) {
        SHStorageManager.putToCache(SHWeexConstants.WEEX, SHWeexConstants.NAME, name);
        SHStorageManager.putToCache(SHWeexConstants.WEEX, SHWeexConstants.DATA, data);

        if (null != callback) {
            callback.invoke(new JSONObject());
        }
    }

当在业务中调用fireGlobalEvent方法时,native会把传入的事件名和data存入缓存。然后执行业务中定义的回调函数,而回调中会有navigator.pop()方法,意味着退出当前weex实例进入到上一个页面。

public void onResume() {
        if (wxInstance != null) {
            wxInstance.onActivityResume();

            String data = SHStorageManager.get(SHWeexConstants.WEEX, SHWeexConstants.DATA, "");

            if (!TextUtils.isEmpty(data)) {
                String name = SHStorageManager.get(SHWeexConstants.WEEX, SHWeexConstants.NAME, "");

                try {
                    JSONObject jsonObj = JSONObject.parseObject(data);
                    Map<String, Object> params = new HashMap<>();
                    for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
                        params.put(entry.getKey(), entry.getValue());
                    }
                    wxInstance.fireGlobalEventCallback(name, params);
                } catch (Exception e) {
                    SHWeexLog.e(e);
                } finally {
                    SHStorageManager.removeFromCache(SHWeexConstants.WEEX, SHWeexConstants.DATA);
                    SHStorageManager.removeFromCache(SHWeexConstants.WEEX, SHWeexConstants.NAME);
                }
            }
        }
    }

然后native会在上一个页面出现时,去缓存中取得之前存入的数据和事件名,再调用官方提供的实例apifireGlobalEventCallback,调用对应的事件,并传数据。

当native中执行了fireGlobalEventCallback这个方法,上一页的事件监听函数就会取得数据。

至此就完成了native中数据的反向传递。

2)weexA(web) > weexB(web), weexB(web) > weexA(web)

反向传递参数在weex的web端就更加好处理了,AB页面都是通过连接后面拼接参数的形式进行传递参数,那么反向传参跟正向传参还是可以按照之前的逻辑进行。

在设计api时特意在回调中会对是否web环境做了判断,因为H5和native在反向传参的行为完全不同,所以判断逻辑会在业务中进行,更方便大家在写业务时进行不同情况不同处理。

fireGlobalEvent('getConpon', {
    id: '3323',
  }, function () {
  if (web) {
      openUrl('/a.html?id=' + '3323');
  } else {
    navigator.pop();
  }
})
@452MJ
Copy link

452MJ commented Nov 20, 2017

请问H5的反向传参weexB(web) > weexA(web)

fireGlobalEvent('getConpon', {
    id: '3323',
  }, function () {
  if (web) {
      openUrl('/a.html?id=' + '3323');
  } else {
    navigator.pop();
  }
})

openUrl('/a.html?id=' + '3323');只能是开启一个新页面,不能做到返回上一级传参吗?按照现在的话,就变成A-B-A了,三级页面

@or0fun
Copy link

or0fun commented Dec 8, 2017

@452MJ H5我们目前无法把参数返回回去,都是跳转页面;native 是可以把参数返回的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants