评论

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

如何通过小程序构建跨平台代码(小程序、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越做越好。

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

16 个评论

  • 王安
    王安
    03-07

    一套代码,运行多端。目前唯一成熟的方案是uni-app,支持App、多家小程序和H5。

    其他方案的坑都太多了。

    [https://uniapp.dcloud.io/]

    可以去看看,案例和开发者数量都是最多的。

    03-07
    赞同 10
    回复 2
    • Maverick
      Maverick
      03-08

      数量最多,以至于质量嘛....DCloud商业宣传能消停点吗

      03-08
      回复
    • 王安
      王安
      03-08回复Maverick

      产品都是免费的,不存在商业。质量肯定是当前最成熟的

      03-08
      回复
  • 连胜
    连胜
    03-07

    跨平台开发,听起来很爽,只用一套代码。

    真要遇到坑了,让你欲哭无泪。

    03-07
    赞同 7
    回复
  • 高雷
    高雷
    03-07

    早该利用成熟的 Web 生态了,小程序也是 WebView,搞了个 Demo 级别的开发工具,可把大家害苦了。

    03-07
    赞同 2
    回复 5
    • 侯全
      侯全
      03-07

      首先,说小程序开发者工具是 Demo 级是很不负责任的,而且代码开发你完全可以不用小程序开发者具的编辑功能,小程序开发者工具的主要作用是本地进行小程序/公众号开发调试 ~


      其次,并不是没有利用成熟的 Web 生态,而且正好相反,微信小程序正是利用了成熟的 Web 生态,只是在安全层面的考虑,对 Web 环境做了较大的限制,同时相对于传统 Web 又集成了微信的能力。


      最后,小程序在开发体验上有较大的缺陷,所以推荐使用 一款小而美的小程序脚手架,让你更流畅的开发小程序

      03-07
      1
      回复
    • 高雷
      高雷
      03-07回复侯全

      最后,小程序在开发体验上有较大的缺陷。


      你这个最后,其实就是证明我的观点,真是把大家坑苦了 。

      03-07
      1
      回复
    • 侯全
      侯全
      03-07回复高雷

      所以,在开发的过程中我开发了一套小程序的脚手架,补全了开发体验上的短板 ~~ 欢迎使用,欢迎 Start ~~

      03-07
      回复
    • 高雷
      高雷
      03-07回复侯全

      第 39 Start,望早日成熟,扬名四海。

      03-07
      回复
    • 侯全
      侯全
      03-07回复高雷

      已经在生产环境中运行了近一年,比较稳定,可以放心使用

      03-07
      回复
  • 陈式坚
    陈式坚
    03-08

    前来支持!

    Omi-mp的确可以解决很大程度上的多端或者小程序框架的不足


    当然适合自己做项目,如果是群发小程序或者移植小程序的还是适合更加成熟的多端框架

    03-08
    赞同 1
    回复
  • Sunrise East
    Sunrise East
    03-07

    小程序本身就该直接用h5,自己搞出的东西真的害死人

    03-07
    赞同 1
    回复
  • 高雷
    高雷
    03-07




    if (typeof window == 'undefined') {

    // 小程序

    }



    typeof window 并不可靠,建议改用 typeof wx == "object" && wx.version

    03-07
    赞同 1
    回复 4
    • joker
      joker
      03-07

      你是在开发工具的控制台输出的,有 window 很正常,因为开发工具就是浏览器来的。

      实际在小程序代码里面输出的话,就是 undefined

      03-07
      回复
    • 高雷
      高雷
      03-07回复joker

      总得在开发工具调试吧?

      03-07
      回复
    • joker
      joker
      03-07回复高雷

      你这是在控制台调试,小程序的代码在开发工具运行的时候,里面 window 就是 undefined。

      控制台的环境不等于小程序的环境

      03-07
      回复
    • 高雷
      高雷
      03-07回复joker

      我个人习惯在控制台写测试代码,妥妥了,直接 IDE 里写,一气呵成,爽。

      03-07
      回复
  • 湫
    03-08

    看到文章,马上把项目拉进来试了一下,结果。。。。。报错

    03-08
    赞同
    回复
  • 哆啦C梦
    哆啦C梦
    03-08

    iOS通过MKWebView加载H5。  这个是WKWebView吧

    03-08
    赞同
    回复
  • joker
    joker
    03-07

    wepy 也好,这个也好,居然是腾讯的。明明小程序也是腾讯,为什么不直接在小程序的框架上改?

    03-07
    赞同
    回复 1
    • yuuk
      yuuk
      03-07

      不同的业务部门咯。

      03-07
      回复
  • meiko
    meiko
    03-07


    这算是什么报错?

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

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

      03-08
      回复

正在加载...