首页前端开发HTML解耦---关于Hybrid H5的跨平台性

解耦---关于Hybrid H5的跨平台性

时间2024-01-26 16:43:03发布访客分类HTML浏览552
导读:收集整理的这篇文章主要介绍了html5教程-解耦---关于Hybrid H5的跨平台性,觉得挺不错的,现在分享给大家,也给大家做个参考。小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。 跨平台,是H...
收集整理的这篇文章主要介绍了html5教程-解耦---关于Hybrid H5的跨平台性,觉得挺不错的,现在分享给大家,也给大家做个参考。小宝典致力于为广大程序猿(媛)提供高品质的代码服务,请大家多多光顾小站,小宝典在此谢过。

跨平台,是H5最重要的能力之一。而 Hybrid H5 因强依赖于具体 app,往往不具有跨平台性。这时,将强依赖关系解耦,即可恢复 H5 的跨平台能力。近期本人负责 手Q 红包打赏项目的前端开发,因项目涉及到多 app 跨平台兼容,对 hybrid H5 的跨平台性有了一定的感悟和思考。在这里做下总结分享,希望能对大家有所收获。

Hybrid H5 跨平台性

进入正题之前,先解释下本文主题的两个名词:

①Hybrid H5,即混合了原生能力的 H5。区别于纯粹 web 端的 H5,它可调用原生的能力,强依赖于具体原生 app,与原生共同构建整个 app 的 UI 层,是 app UI 层很好的灵活性补充。微信和 手Q 上的 H5 业务一般都属于 Hybrid H5 的范畴。

② 跨平台性,即一个 H5 页面可同时运行在多个平台上。可运行平台越多,跨平台性就越强。在如今移动互联网的发展大潮中,H5 能与体验更优的原生终端齐步并进,其跨平台性可谓功不可没。

因强依赖于具体 app,Hybrid H5 往往不具有跨平台性。

本文将从 Hybrid H5 与原生的通讯原理出发,逐步探讨如何通过解耦来恢复 Hybrid H5 的跨平台性。

Hybrid H5 与原生的通讯原理

原理图

从原理图中,有4个关键点:

1个通讯媒介——原生自定义的通讯协议;

以及围绕着通讯媒介执行的3个通讯行为vc3Ryb25nPiZtZGFzaDsmbWRhc2g7tKW3oqGITffTw6Giu9i196GjPC9wPg0KPHA+PHN0cm9uZz652Lz8tePP6r3iPC9zdHJvbmc+PC9wPg0KPHA+PHN0cm9uZz6i2c2o0bbDvb3pJm1kYXNoOyZtZGFzaDvUrcn6zajRttCt0uk8L3N0cm9uZz6jutStyfrX1Lao0uW1XM6x0K3S6aOs0ruw47vhtqjS5bPJ0+sgahr0cCDQrdLpwODLxrXEuPHKvaO6PC9wPg0KPHA+0K3S6cP7Oi8vvdO/2sK3vrY/ss7K/TE9WFhYJmFtcDuyzsr9Mj1YWFgmYW1wO7LOyv0zpvhYWCNjYWxsYmFjazwvcD4NCjxWPSbk1tCjujwvcD4NCjxwPmGhotCt0unD+6O6YXBwINfUtqjS5bXE0K3S6cP7o6zTw9PaSDW0pbei0NDOqrXEvOC/2LK2u/GjrMjnIMrWUSDKudPDtcQganNicMLkZ2U6Ly+juzxiciAvPg0KYqGivdO/2sK3vrajutStyfq+38zlxNzBpsK3vrajrLK7zazUrcn6xNzBpsK3vrayu82so7s8YnIgLz4NCmOhorLOyv0xpVhYWCZhbXA7ss7K/TI9WFhYJmFtcDuyzsr9Mz1YWFgjY2FsbGJhY2ujukg1tKuyztPRu9i197e9t6ix6sq2o7s8L3A+DQo8cD64+b7dzajRttCt0um55re2o6y8tL/J1eu21LK7zay1xNStyfrE3MGmuPhINczhuamyu82stcS199PDtdjWt6OsyOejujwvcD4NCjxwcmUgY2xhc3M9"brush:java; "> jsbridge://method?a=2& b=3#h5MethodTag

②通讯行为——触发:能被原生监听并捕获截拦的H5行为,都可以作为原生通讯协议的触发行为。

Hybrid H5 的这类行为有 console.LOG、alert、confirm、prompt、location.href 等。将原生协议内容通过其中的某一行为触发,即可被原生正确捕获并解析。如:

 location.href ='jsbridge://method?a=2&
    b=3#h5MethodTag' 

H5调用后,原生终端会捕获到内容:jsbridge://method?a=2& b=3#h5MethodTag

③通讯行为——调用:原生终端根据 H5 传过来的内容,解析匹配后会路由到具体处理方法,执行原生能力逻辑。以 ios 为例(swift 语言),“调用”逻辑如下:

 func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationTyPE: UIWebViewNavigationType) - Bool {
         let url = request.URL //url     let scheme = url ? .scheme //协议名     let method = url ? .host //接口路径     let query = url ? .query //参数      if url != nil &
    &
 scheme == "jsbridge" {
         /*根据method路由*/         switch method!{
             case "method":                     self.method()             case "openTenpayView":                     self.openTenpayView()             ...其他方法...             default:         }
         return false     }
 else {
         return true     }
 }
     

原生终端根据捕获到的协议内容,进行解析获取,若伪协议为原生指定的伪协议(“jsbridge”),就会根据 method 内容和 query 参数进行路由操作,寻找具体的方法执行逻辑。否则,忽略处理,按照 webview 原有跳转逻辑处理。以第②步触发的伪协议内容为例,在本例“调用”代码中被原生捕获后,会路由执行逻辑:self.method();

④通讯行为——回调:原生根据 H5 传过来的内容,捕获 js 回调函数方法名,在原生逻辑执行结束后,将执行结果带到回调函数中并执行 js 回调函数。通过在第③步“调用”执行完后,ios 会调用 js 回调函数 H5MethodTag:

 /*解析到H5的回调函数名为H5MethodTag(#号后内容),回调执行js的方法*/ webview.stringByEvaluatingJavaScriptFromString("H5MethodTag(data)")  

通过以上4个关键点,即可做到 H5 与原生终端的相互通讯,完成H5对原生能力的调用。

初次解耦:app 内跨平台——创建jsapi解耦通讯逻辑、封装平台差异

由上述通讯原理了解到,Hybrid H5 直接调用定义好的原生通讯协议,即可完成通讯全过程。但这里有一个明显的问题,即 Hybrid H5 会强耦合于当前平台。不说跨 app 了,app 内跨平台(andROId/ios/wp)都会显示吃力。这里面有很多原因,其中一个较明显的原因在于,不同平台 app 开发团队通讯协议规范定义存在不一致。再者,H5 业务代码上满满的类似 jsonp 的协议调用,也并不好维护。

要达到 Hybrid H5 在 app 内跨平台,业界常见做法是 app 对外提供 jsapi。通过 jsapi 将各平台协议规范差异进行封装,解耦通讯逻辑,并以函数接口的方式提供给 Hybrid H5 调用。jsapi 接口一般会定义成如下格式:

 ns.method({
     /*CFg参数对象*/ }
, function(data) {
     /*回调*/ }
) 

原理图

**原理核心:**H5 与原生通讯之间增加一层 jsapi,jsapi 完成三大行为:api 接口创建、协议 url 组装、创建 iframe 发起伪协议请求;

因 手Q 的 jsapi 相对比较成熟,下面会以 手Q jsapi 中的核心源码进行分析。

**①api接口创建:**js 函数接口封装、平台差异处理,方便H5函数调用

 mQQ.build('mqq.tenpay.openTenpayView', {
     iOS: function(options, callback) {
             VAR callbackName = callback ? mqq.callback(callback) : null;
         mqq.invokeClient('pay', 'openTenpayView', {
             'params': options,             'callback': callbackName         }
    );
     }
,     android: function(params, callback) {
             mqq.invokeClient('pay', 'openTenpayView', JSON.stringify(params), callback);
     }
,     supportInvoke: true,     support: {
         iOS: '4.6.1',         android: '4.6.1'     }
 }
    );
 

mqq.build 方法为 api 接口创建方法。通过传入待创建的 jsapi 方法名(mqq.tenpay.openTenpayView)和不同平台(android/ios)的差异处理配置。最终会生成H5可调用方法:

 mqq.tenpay.openTenpayView({
     /*data*/ }
,function(ret){
     /*callback*/ }
    ) 

②协议url组装:从接口到 url 协议的转换、回调处理,完成协议 url 创建

第①步中,不同平台差异处理都会调用 mqq.invokeClient 方法,该方法实际处理的就是原理图中与原生通讯的过程。我们先来看协议 url 组装的过程。

 /*生成回调索引*/ sn = StoreCallback(callback);
     /*协议路径组装*/ url = 'jsbridge://' + encodeURIcomponent(ns) + '/' + encodeURIComponent(method);
 /*参数组装*/ argus.foreach(function(a, i) {
     if (exports.isObject(a)) {
         a = JSON.stringify(a);
     }
     if (i === 0) {
             url += '?p=';
     }
 else {
             url += '&
    p' + i + '=';
     }
         url += encodeURIComponent(String(a));
 }
    );
     /*回调函数索引组装*/ url += '#' + sn;
     /*链接调用*/ result = openURL(url, ns, method);
     

协议 url 组装的过程实际上是对传入参数按协议规范进行拼串的过程,其中包括匿名回调函数的回调索引创建、协议名& 协议路径拼串、传参循环遍历拼串。

③创建 iframe 发起伪协议请求:请求触发

 /*创建隐藏iframe*/ var iframe = document.createElement('iframe');
     iframe.style.cssText = 'display:none;
    width:0px;
    height:0px;
    ';
  function failCallback() {
     /*错误处理*/ }
     /*iframe协议调用*/ iframe.onload = failCallback;
     iframe.src = url;
     (document.body || document.documentElement).appendChild(iframe);
  /*删除iframe*/ setTimeout(function() {
         iframe &
    &
     iframe.parentNode &
    &
     iframe.parentNode.removeChild(iframe);
 }
    , 0);
     

通过创建 iframe 来完成协议调用,并在调用结束后将 iframe 删除,即可在不影响原 H5 流程的情况下完成调用全过程。

再次解耦:app 间跨平台—— jsapi 细化,封装 app 差异

通过上述的解耦处理,Hybrid H5 已经可以在 app 内各平台运行了。但往往这种 jsapi 是 app 级提供的 jsapi(下面简称 app jsapi),app jsapi 并不会去兼容别的 app 的差异。而实际情况具体到某一 Hybrid H5,尤其是与 app 外部合作的 Hybrid H5,则并不仅仅只运行在一个 app上。比如信用卡还款业务,微信有,手Q 也有,功能都一样。这种情况就需要进一步的解耦,从业务侧再抽离一层 jsapi(下面简称 H5 jsapi)来处理 app 间的差异,而非每个 app 各自一套 H5。

原理图

**原理核心:**Hybrid H5 业务上增加多一层自维护的 H5 jsapi,H5 jsapi 完成两大行为:app jsapi 差异请求、app jsapi 差异封装。

①app jsapi 差异请求:根据当前运行环境 app 请求具体的 app jsapi

下面以 Hybrid H5 需同时运行在手Q和空间独立版的 app jsapi 差异请求处理逻辑。

 script type="text/javascript" >
     (function() {
             var ua = navigator.userAgent || "",             isQQ = ua.match(/QQ//([/d/.]+)/),             isQzone = ua.match("Qzone");
         if (isQQ) {
                 document.write("script src='https://open.mobile.qq.COM/sdk/qqapi.js?_bid=152'>
    ");
         }
 else if (isQzone) {
                 document.write("script src='https://qzonestyle.gtimg.cn/qzone/phone/m/v4/widget/mobile/jsbridge.js'>
    ");
         }
 else {
                 // 不是已兼容app,跳转到兼容app上运行             var currentHref = window.location.href;
                 /*跳转到手Q打开本页面*/             window.location.href = 'mqqapi://forward/url?url_prefix=' + BToa(currentHref) + '&
    version=1&
    src_type=web';
             /*该页面支持自定义弹层*/             setTimeout(function() {
                     var _tempBox = confirm('请在手机QQ中使用~');
                 if (_tempBox == true) {
                         /*跳至手Q打开*/                     window.location.href = 'mqqapi://forward/url?url_prefix=' + btoa(currentHref) + '&
    version=1&
    src_type=web';
                 }
             }
, 0)         }
     }
    )() /script>
 

除了对需兼容的 app 进行差异请求外,还应对在不兼容的 app 运行时做跳转到主兼容 app 打开当前页面的逻辑处理,并做引导性提示,保障页面的完整可用性。

②app jsapi 差异封装:根据当前具体运行的平台调用相应的 app jsapi 接口。H5 jsapi 的接口形式尽量与主运行 app 的 jsapi 保持一致

下面以打开 QQ 钱包原生页和原生页面跳转能力为例,做 app jsapi 的差异封装。

 var mod = {
     ...     openTenpayView: function(param, callback) {
         if (isQQ) {
             var param = $.extend({
                 userId: $.getCookie('uin').replace(/^o0*/, '')             }
    , param);
                 mqq.tenpay.openTenpayView(param, callback);
         }
 else {
                 /*调起手Q打开中转页jump.html,由中转页打开原生功能页*/             var targetHref = 'https://testhost.com/jump.html?go=' + param.viewTag + '&
    _wv=' + (1 + 2 + 1024 + 2097152 + 33554432);
     //跳转url             /*跳到手Q*/             window.location.href = 'mqqapi://forward/url?url_prefix=' + btoa(targetHref) + '&
    version=1&
    src_type=web';
         }
     }
,     openUrl: function(paramObj) {
         if (isQQ) {
             mqq.ui.openUrl({
                 url: paramObj.url,                 target: 1             }
    );
         }
 else if (isQzone) {
             mqq.invoke("ui", "openUrl", {
                 url: paramObj.url,                 target: 1,                 style: 1             }
    );
         }
 else {
             /*兼容处理*/             location.href = paramObj.url         }
     }
,     ...其他接口... }
    ;
     return mod;
     

调用 openTenpayView,页面能在 手Q 中正常调用,而在非 手Q 时则跳转回 手Q 打开处理;

调用 openUrl,对于 手Q 和空间独立版做相应的接口调用,而其他平台则直接使用 H5 的 location 跳转。

总结

H5 本质是具有跨平台性的。Hybrid H5 因混合了原生能力,强耦合于原生,不再具有跨平台性。要恢复其跨平台能力,关键在解耦,将其耦合于原生的部分解耦封装起来。

解耦是开发很重要的一项能力,Hybrid H5 跨平台性的回归正得益于解耦的处理。

因耦合而导致某项能力减弱的情况还有很多,比如 H5 的灵活性等等。遇到这种情况大家不妨也试试解耦,或许会收到意想不到的惊喜。

 

跨平台,是H5最重要的能力之一。而 Hybrid H5 因强依赖于具体 app,往往不具有跨平台性。这时,将强依赖关系解耦,即可恢复 H5 的跨平台能力。近期本人负责 手Q 红包打赏项目的前端开发,因项目涉及到多 app 跨平台兼容,对 hybrid H5 的跨平台性有了一定的感悟和思考。在这里做下总结分享,希望能对大家有所收获。

Hybrid H5 跨平台性

进入正题之前,先解释下本文主题的两个名词:

①Hybrid H5,即混合了原生能力的 H5。区别于纯粹 web 端的 H5,它可调用原生的能力,强依赖于具体原生 app,与原生共同构建整个 app 的 UI 层,是 app UI 层很好的灵活性补充。微信和 手Q 上的 H5 业务一般都属于 Hybrid H5 的范畴。

② 跨平台性,即一个 H5 页面可同时运行在多个平台上。可运行平台越多,跨平台性就越强。在如今移动互联网的发展大潮中,H5 能与体验更优的原生终端齐步并进,其跨平台性可谓功不可没。

因强依赖于具体 app,Hybrid H5 往往不具有跨平台性。

本文将从 Hybrid H5 与原生的通讯原理出发,逐步探讨如何通过解耦来恢复 Hybrid H5 的跨平台性。

Hybrid H5 与原生的通讯原理

原理图

从原理图中,有4个关键点:

1个通讯媒介——原生自定义的通讯协议;

以及围绕着通讯媒介执行的3个通讯行为vc3Ryb25nPiZtZGFzaDsmbWRhc2g7tKW3oqGitffTw6Giu9i196GjPC9wPg0KPHA+PHN0cm9uZz652Lz8tePP6r3iPC9zdHJvbmc+PC9wPg0KPHA+PHN0cm9uZz6i2c2o0bbDvb3pJm1kYXNoOyZtZGFzaDvUrcn6zajRttCt0uk8L3N0cm9uZz6jutStyfrX1Lao0uW1xM6x0K3S6aOs0ruw47vhtqjS5bPJ0+sgaHR0cCDQrdLpwODLxrXEuPHKvaO6PC9wPg0KPHA+0K3S6cP7Oi8vvdO/2sK3vrY/ss7K/TE9WFhYJmFtcDuyzsr9Mj1YWFgmYW1wO7LOyv0zPVhYWCNjYWxsYmFjazwvcD4NCjxwPsbk1tCjujwvcD4NCjxwPmGhotCt0unD+6O6YXBwINfUtqjS5bXE0K3S6cP7o6zTw9PaSDW0pbei0NDOqrXEvOC/2LK2u/GjrMjnIMrWUSDKudPDtcQganNicmlkZ2U6Ly+juzxiciAvPg0KYqGivdO/2sK3vrajutStyfq+38zlxNzBpsK3vrajrLK7zazUrcn6xNzBpsK3vrayu82so7s8YnIgLz4NCmOhorLOyv0xPVhYWCZhbXA7ss7K/TI9WFhYJmFtcDuyzsr9Mz1YWFgjY2FsbGJhY2ujukg1tKuyztPru9i197e9t6ix6sq2o7s8L3A+DQo8cD64+b7dzajRttCt0um55re2o6y8tL/J1eu21LK7zay1xNStyfrE3MGmuPhINczhuamyu82stcS199PDtdjWt6OsyOejujwvcD4NCjxwcmUgY2xhc3M9"brush:java; "> jsbridge://method?a=2& b=3#h5MethodTag

②通讯行为——触发:能被原生监听并捕获截拦的H5行为,都可以作为原生通讯协议的触发行为。

Hybrid H5 的这类行为有 console.log、alert、confirm、prompt、location.href 等。将原生协议内容通过其中的某一行为触发,即可被原生正确捕获并解析。如:

 location.href ='jsbridge://method?a=2&
    b=3#h5MethodTag' 

H5调用后,原生终端会捕获到内容:jsbridge://method?a=2& b=3#h5MethodTag

③通讯行为——调用:原生终端根据 H5 传过来的内容,解析匹配后会路由到具体处理方法,执行原生能力逻辑。以 ios 为例(swift 语言),“调用”逻辑如下:

 func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) - Bool {
         let url = request.URL //url     let scheme = url ? .scheme //协议名     let method = url ? .host //接口路径     let query = url ? .query //参数      if url != nil &
    &
 scheme == "jsbridge" {
         /*根据method路由*/         switch method!{
             case "method":                     self.method()             case "openTenpayView":                     self.openTenpayView()             ...其他方法...             default:         }
         return false     }
 else {
         return true     }
 }
     

原生终端根据捕获到的协议内容,进行解析获取,若伪协议为原生指定的伪协议(“jsbridge”),就会根据 method 内容和 query 参数进行路由操作,寻找具体的方法执行逻辑。否则,忽略处理,按照 webview 原有跳转逻辑处理。以第②步触发的伪协议内容为例,在本例“调用”代码中被原生捕获后,会路由执行逻辑:self.method();

④通讯行为——回调:原生根据 H5 传过来的内容,捕获 js 回调函数方法名,在原生逻辑执行结束后,将执行结果带到回调函数中并执行 js 回调函数。通过在第③步“调用”执行完后,ios 会调用 js 回调函数 H5MethodTag:

 /*解析到H5的回调函数名为H5MethodTag(#号后内容),回调执行js的方法*/ webview.stringByEvaluatingJavaScriptFromString("H5MethodTag(data)")  

通过以上4个关键点,即可做到 H5 与原生终端的相互通讯,完成H5对原生能力的调用。

初次解耦:app 内跨平台——创建jsapi解耦通讯逻辑、封装平台差异

由上述通讯原理了解到,Hybrid H5 直接调用定义好的原生通讯协议,即可完成通讯全过程。但这里有一个明显的问题,即 Hybrid H5 会强耦合于当前平台。不说跨 app 了,app 内跨平台(android/ios/wp)都会显示吃力。这里面有很多原因,其中一个较明显的原因在于,不同平台 app 开发团队通讯协议规范定义存在不一致。再者,H5 业务代码上满满的类似 jsonp 的协议调用,也并不好维护。

要达到 Hybrid H5 在 app 内跨平台,业界常见做法是 app 对外提供 jsapi。通过 jsapi 将各平台协议规范差异进行封装,解耦通讯逻辑,并以函数接口的方式提供给 Hybrid H5 调用。jsapi 接口一般会定义成如下格式:

 ns.method({
     /*cfg参数对象*/ }
, function(data) {
     /*回调*/ }
) 

原理图

**原理核心:**H5 与原生通讯之间增加一层 jsapi,jsapi 完成三大行为:api 接口创建、协议 url 组装、创建 iframe 发起伪协议请求;

因 手Q 的 jsapi 相对比较成熟,下面会以 手Q jsapi 中的核心源码进行分析。

**①api接口创建:**js 函数接口封装、平台差异处理,方便H5函数调用

 mqq.build('mqq.tenpay.openTenpayView', {
     iOS: function(options, callback) {
             var callbackName = callback ? mqq.callback(callback) : null;
         mqq.invokeClient('pay', 'openTenpayView', {
             'params': options,             'callback': callbackName         }
    );
     }
,     android: function(params, callback) {
             mqq.invokeClient('pay', 'openTenpayView', JSON.stringify(params), callback);
     }
,     supportInvoke: true,     support: {
         iOS: '4.6.1',         android: '4.6.1'     }
 }
    );
 

mqq.build 方法为 api 接口创建方法。通过传入待创建的 jsapi 方法名(mqq.tenpay.openTenpayView)和不同平台(android/ios)的差异处理配置。最终会生成H5可调用方法:

 mqq.tenpay.openTenpayView({
     /*data*/ }
,function(ret){
     /*callback*/ }
    ) 

②协议url组装:从接口到 url 协议的转换、回调处理,完成协议 url 创建

第①步中,不同平台差异处理都会调用 mqq.invokeClient 方法,该方法实际处理的就是原理图中与原生通讯的过程。我们先来看协议 url 组装的过程。

 /*生成回调索引*/ sn = storeCallback(callback);
     /*协议路径组装*/ url = 'jsbridge://' + encodeURIComponent(ns) + '/' + encodeURIComponent(method);
 /*参数组装*/ argus.forEach(function(a, i) {
     if (exports.isObject(a)) {
         a = JSON.stringify(a);
     }
     if (i === 0) {
             url += '?p=';
     }
 else {
             url += '&
    p' + i + '=';
     }
         url += encodeURIComponent(String(a));
 }
    );
     /*回调函数索引组装*/ url += '#' + sn;
     /*链接调用*/ result = openURL(url, ns, method);
     

协议 url 组装的过程实际上是对传入参数按协议规范进行拼串的过程,其中包括匿名回调函数的回调索引创建、协议名& 协议路径拼串、传参循环遍历拼串。

③创建 iframe 发起伪协议请求:请求触发

 /*创建隐藏iframe*/ var iframe = document.createElement('iframe');
     iframe.style.cssText = 'display:none;
    width:0px;
    height:0px;
    ';
  function failCallback() {
     /*错误处理*/ }
     /*iframe协议调用*/ iframe.onload = failCallback;
     iframe.src = url;
     (document.body || document.documentElement).appendChild(iframe);
  /*删除iframe*/ setTimeout(function() {
         iframe &
    &
     iframe.parentNode &
    &
     iframe.parentNode.removeChild(iframe);
 }
    , 0);
     

通过创建 iframe 来完成协议调用,并在调用结束后将 iframe 删除,即可在不影响原 H5 流程的情况下完成调用全过程。

再次解耦:app 间跨平台—— jsapi 细化,封装 app 差异

通过上述的解耦处理,Hybrid H5 已经可以在 app 内各平台运行了。但往往这种 jsapi 是 app 级提供的 jsapi(下面简称 app jsapi),app jsapi 并不会去兼容别的 app 的差异。而实际情况具体到某一 Hybrid H5,尤其是与 app 外部合作的 Hybrid H5,则并不仅仅只运行在一个 app上。比如信用卡还款业务,微信有,手Q 也有,功能都一样。这种情况就需要进一步的解耦,从业务侧再抽离一层 jsapi(下面简称 H5 jsapi)来处理 app 间的差异,而非每个 app 各自一套 H5。

原理图

**原理核心:**Hybrid H5 业务上增加多一层自维护的 H5 jsapi,H5 jsapi 完成两大行为:app jsapi 差异请求、app jsapi 差异封装。

①app jsapi 差异请求:根据当前运行环境 app 请求具体的 app jsapi

下面以 Hybrid H5 需同时运行在手Q和空间独立版的 app jsapi 差异请求处理逻辑。

 script type="text/javascript" >
     (function() {
             var ua = navigator.userAgent || "",             isQQ = ua.match(/QQ//([/d/.]+)/),             isQzone = ua.match("Qzone");
         if (isQQ) {
                 document.write("script src='https://open.mobile.qq.com/sdk/qqapi.js?_bid=152'>
    ");
         }
 else if (isQzone) {
                 document.write("script src='https://qzonestyle.gtimg.cn/qzone/phone/m/v4/widget/mobile/jsbridge.js'>
    ");
         }
 else {
                 // 不是已兼容app,跳转到兼容app上运行             var currentHref = window.location.href;
                 /*跳转到手Q打开本页面*/             window.location.href = 'mqqapi://forward/url?url_prefix=' + btoa(currentHref) + '&
    version=1&
    src_type=web';
             /*该页面支持自定义弹层*/             setTimeout(function() {
                     var _tempBox = confirm('请在手机QQ中使用~');
                 if (_tempBox == true) {
                         /*跳至手Q打开*/                     window.location.href = 'mqqapi://forward/url?url_prefix=' + btoa(currentHref) + '&
    version=1&
    src_type=web';
                 }
             }
, 0)         }
     }
    )() /script>
 

除了对需兼容的 app 进行差异请求外,还应对在不兼容的 app 运行时做跳转到主兼容 app 打开当前页面的逻辑处理,并做引导性提示,保障页面的完整可用性。

②app jsapi 差异封装:根据当前具体运行的平台调用相应的 app jsapi 接口。H5 jsapi 的接口形式尽量与主运行 app 的 jsapi 保持一致

下面以打开 QQ 钱包原生页和原生页面跳转能力为例,做 app jsapi 的差异封装。

 var mod = {
     ...     openTenpayView: function(param, callback) {
         if (isQQ) {
             var param = $.extend({
                 userId: $.getCookie('uin').replace(/^o0*/, '')             }
    , param);
                 mqq.tenpay.openTenpayView(param, callback);
         }
 else {
                 /*调起手Q打开中转页jump.html,由中转页打开原生功能页*/             var targetHref = 'https://testhost.com/jump.html?go=' + param.viewTag + '&
    _wv=' + (1 + 2 + 1024 + 2097152 + 33554432);
     //跳转url             /*跳到手Q*/             window.location.href = 'mqqapi://forward/url?url_prefix=' + btoa(targetHref) + '&
    version=1&
    src_type=web';
         }
     }
,     openUrl: function(paramObj) {
         if (isQQ) {
             mqq.ui.openUrl({
                 url: paramObj.url,                 target: 1             }
    );
         }
 else if (isQzone) {
             mqq.invoke("ui", "openUrl", {
                 url: paramObj.url,                 target: 1,                 style: 1             }
    );
         }
 else {
             /*兼容处理*/             location.href = paramObj.url         }
     }
,     ...其他接口... }
    ;
     return mod;
     

调用 openTenpayView,页面能在 手Q 中正常调用,而在非 手Q 时则跳转回 手Q 打开处理;

调用 openUrl,对于 手Q 和空间独立版做相应的接口调用,而其他平台则直接使用 H5 的 location 跳转。

总结

H5 本质是具有跨平台性的。Hybrid H5 因混合了原生能力,强耦合于原生,不再具有跨平台性。要恢复其跨平台能力,关键在解耦,将其耦合于原生的部分解耦封装起来。

解耦是开发很重要的一项能力,Hybrid H5 跨平台性的回归正得益于解耦的处理。

因耦合而导致某项能力减弱的情况还有很多,比如 H5 的灵活性等等。遇到这种情况大家不妨也试试解耦,或许会收到意想不到的惊喜。

 

觉得可用,就经常来吧! 欢迎评论哦! html5教程,巧夺天工,精雕玉琢。小宝典献丑了!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

APIClassCSSdivexportHTMLletpost-format-gallery数组

若转载请注明出处: 解耦---关于Hybrid H5的跨平台性
本文地址: https://pptw.com/jishu/587015.html
HTML5+规范:navigator(管理浏览器运行环境信息) HTML5+规范:Uploader(管理网络上传任务)

游客 回复需填写必要信息