评论

如何通过小程序实现跨平台开发

如何通过小程序构建跨平台代码(小程序、APP、H5、公众号)

背景

前段时间要做一系列的测试工具,需要在多平台:iOS、android、H5、公众号、小程序都实现。功能基本一样,就是在支付步骤需要区分平台,用对应的支付方式支付。本文讨论如何用一套小程序代码实现上述5个平台的开发。

效果图(左边为小程序,右边为浏览器):

omi-mp的介绍

omi-mp是腾讯前端框架omi的一个工具集,其目的是在于将小程序代码转成H5/Web,具体可以参见omi-mp的介绍Github

omi-mp的转换并不是完全兼容小程序所有特性的,只支持了一小部分小程序API,并且存在了一些兼容特性,因此就需要开发者在开发小程序代码时,更多的以开发H5/Web的思路开发

思路图和实现步骤

先实现小程序代码

1.初始化omi-mp目录工程:

npm i omi-cli -g
omi init-mp {工程名称}
cd {工程名称}
npm install

2.把小程序项目拷贝到src-mp目录。
3.建议边实现小程序的过程中,不断的检验生成的H5的正确性,避免在最后阶段检验,否则如果出现问题,将不好定位,本地运行H5命令:

npm start  //开发

再将小程序打包成H5/Web

打包H5/Web命令:

npm run build  //发布
  • 发布需要确认域名,修改package.json文件,修改"build": "PUBLIC_URL={发布域名} node scripts/build.js"
  • 如果存在部分js文件丢失,可以尝试执行
gulp copyThen

公众号直接加载H5

公众号本质上也属于H5。

iOS/android App通过内嵌网页加载H5

iOS通过MKWebView加载H5。
android通过WebView加载H5。

  • H5和原生App的交互部分可以通过JSBridge或者URL拦截实现

小程序代码如何区分平台

综上所述,除去部分iOS/android的原生代码外,基本所有的逻辑都是放在小程序里,按不同平台实现不同逻辑,小程序可以通过UserAgent以及Dom区分:

  • 如果Dom树不存在window或者document,为小程序平台;
  • iOS/android App内嵌网页可以自定义特殊的UserAgent,小程序代码可以通过此来区分iOS/android App平台;
  • 微信App内嵌浏览器的UserAgent会带入MicroMessenger/关键字,可以按此区分公众号平台;
  • 其余为H5/Web平台;
if (typeof window == 'undefined') {
	// 小程序
} else {
	if (navigator.userAgent.userAgent.indexOf('ios-app') != -1
		|| navigator.userAgent.userAgent.indexOf('android-app') != -1) {
		// iOS/android
	} else if (this.globalData.userAgent.indexOf('MicroMessenger/') != -1) {
		// 公众号
	} else {
		// Web
	}
}

iOS/android原生代码如何桥接

1.iOS/android需要先设置特殊UserAgent让小程序代码知道是iOS/android平台

iOS:

NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"ios-app", @"UserAgent", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dictionary];

android:

webView.getSettings().setUserAgentString("android-app");

2.以URL拦截为例,小程序代码在当处于iOS/android平台的情况下,可以发送特殊URL,让iOS/android原生代码处理:

小程序:

if (navigator.userAgent.userAgent.indexOf('ios-app') != -1
	|| navigator.userAgent.userAgent.indexOf('android-app') != -1) {
let url = 'app://pay?' + query;
window.location.href = url;
}

3.iOS/android拦截URL特殊处理

iOS:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
	NSURL * url = navigationAction.request.URL;
	if ([url.absoluteString hasPrefix:@"app://pay"]) {
		// do something...
		decisionHandler(WKNavigationActionPolicyCancel);
		return;
	}
	decisionHandler(WKNavigationActionPolicyAllow);
}

android:

webView.setWebViewClient(new WebViewClient(){
	public boolean shouldOverrideUrlLoading(WebView view, String url) {
		if (url.startsWith("app://pay")) {
			// do something...
			return true;
		}
		return false;
	}
});

omi-mp的部分缺陷和一些踩过的坑

1.目前omi-mp只支持部分小程序部分API:

- wx.request
- wx.navigateTo
- wx.navigateBack
- wx.getSystemInfo
- wx.getSystemInfoSync
- wx.setNavigationBarTitle
- this.setData
- this.triggerEvent

如果用了其他的API,那么将会在输出H5报错。

2.支持组件,但是不支持组件的函数直接调用,替代方案可以用mitt,在page和component之间用mitt消息传递。

3.如果需要同时输出H5和Web,那么需要同时绑定clicktap事件(小程序只能绑定tap,Web只能绑定click,H5两者都可以),但是同时绑定又将会造成在H5的情况下,clicktap都会回调,导致两次调用。解决办法是可以在clicktap的地方同时加上判断,避免两次调用:

handleTap(e) {
	if (!((typeof window == 'undefined') && e.type === "tap")) {
		return;
	} else if (!((typeof window != 'undefined') && e.type === "click")) {
		return;
	}
	// do something...
}

4.wxml不支持Object字段的遍历处理。

5.如果编译不过,那么确认下是不是wxml中存在了一些特殊关键字,与omi的重了,导致失败。

6.即便在H5的场景下也无法使用document.getElementById()。但是有替代方案,只是比较麻烦。

7.还有其它缺陷,有些忘了,待补充。

结语

omi-mp是一个不错的工具,在小程序不断变大变强的今天,能做到一套小程序代码,多端运行,降低开发成本。这里尤其感谢dntzhang的大力支持,希望omi越做越好。

最后一次编辑于  2019-04-12  
点赞 10
收藏
评论

17 个评论

  • 今天也很好
    今天也很好
    2019-03-07


    这算是什么报错?

    2019-03-07
    赞同
    回复 1
    • dntzhang(张磊)
      dntzhang(张磊)
      2019-03-08

      进群 256426170,然后把源码发给群主

      2019-03-08
      回复
  • 晓初
    晓初
    2019-03-07

    wepy都不用,用原生的人,还敢搞这个多端(滑稽)

    2019-03-07
    赞同
    回复
  • 2019-03-07

    支持。

    2019-03-07
    赞同
    回复
  • 老张
    老张
    2019-03-07

    这绝B是个坑王。

    2019-03-07
    赞同
    回复
  • 阿巴阿巴
    阿巴阿巴
    2019-03-07

    这些东西很多都是理论层次,如果真想发展起来,需要不断根据使用者的需求去优化完善框架,但是回应期就不敢说何年何月了

    共勉

    2019-03-07
    赞同
    回复
  • 阿巴阿巴
    阿巴阿巴
    2019-03-07

    一套代码运行多端的坑太多了.后端不是也天天喊跨平台,一直没有成功。都一样。难。


    2019-03-07
    赞同
    回复
  • 哆啦A乐
    哆啦A乐
    2019-03-07

    一套代码运行多端的坑太多了

    2019-03-07
    赞同
    回复

正在加载...

登录 后发表内容