2、在 运行时 阶段又做了哪些事情呢?...
主要在每个js文件头部加入了适配代码adaptor.js
截取部分实现代码如下: 源代码可参考converter.js
function convert(opt = {}) { const src = opt.source || './src'; const dest = opt.target || './alibaba'; const assets = opt.assets || config.getAssets(src); ...省略 // 注入适配器代码 gulp.src(sysPath.resolve(__dirname, '../../../node_modules/mp-adaptor/lib/alibaba.js')) .pipe(rename('adaptor.js')) .pipe(gulp.dest(dest)).on('end', () => { logger.info('复制 adaptor.js 完成!'); }); // 处理脚本文件 gulp.src(`${src}/**/*.js`) .pipe(replace(/[\s\S]*/g, (match) => converter.script(match))) .pipe(through2.obj(function(file, enc, cb) { const path = file.history[0].replace(file.base, ''); const spec = path.split(sysPath.sep); const adaptor = new Array(spec.length - 1).fill('..').concat('adaptor.js').join('/'); const str = [ `import wx from '${adaptor.replace(/^\.\./, '.')}';`, ab2str(file.contents) ].join('\r\n'); file.contents = str2ab(str); this.push(file); cb(); })) .pipe(gulp.dest(dest)); } module.exports = convert;
加入的adapter.js 代码是什么样的呢? 参考源码alibaba.js
function getInstance() { // eslint-disable-next-line no-undef const wx = my; wx.has_ali_hook_flag = true; const { getSystemInfo } = wx; wx.getSystemInfo = function(opt) { ...省略 return getSystemInfo.call(this, opt); }; ...省略 return wx; } export default getInstance(); 上面的适配代码:主要就是包装抹平微信与支付宝两个平台间api的调用差异,既可以使用原微信wx.*的方式来调用,也可以使用支付宝小程序平台my.*的方式来调用api,说白了就是对微信的api包装了一层。
通过分析 wwto 这个工具库的实现过程,也就学习到了如何基于现有的微信小程序转其他平台小程序的实现过程了。下面说下这次转换的过程中遇到了那些问题以及怎么解决的。
微信小程序代码转换阶段-实践
转换的时候遇见这么一些问题:
首先,wwto工具做不到运行时 diff 的抹平,也做不到一个 API 从无到有的过程
1、现阶段我们的微信小程序依赖 vantUI 组件库,使用wwto来转换压根就不支持
2、微信小程序中常用的api:selectComponent 在支付宝里小程序里面不支持
3、微信的分包加载是否支持?不支持又该如何处理等?
对于第二个问题,需要修改 wwto 工具库的代码,使其支持这个api,我这边的实现思路如下: 如Page A 页面依赖 Component B组件,可以在B组件的ready生命周期阶段把当前组件实例this挂载到全局对象getApp()中的某个属性上,然后在Page A中实现selectComponent这个api,这个api就来获取挂载到getApp()上对应的实例组件。
修改处在script.js代码中,可以打开文件比对 如下:
对于第三个问题,通过了解支付宝的分包机制文档,完全可以支持微信小程序的,但是,这里我在调试的时候支付宝开发者工具和到真机预览的时,两者差异完全不一样,在开发者工具完全运行正常,可是在真机预览的时候会遇见各种奇葩问题,大部分都是adaptor.js 重写wx.* 的api导致的问题,通过调试了好长时间,终于找到了问题的根源所在,我已经在githup上 向wwto 开源者提issue了,可查看adaptor.js 重复执行 了解,并且我已提交了PR进行了修正
对于第二个大问题,做的事就相对比较多了,如果在不了解wwto这个工具库代码实现思路情况下,可能是无法解决的,当时能想到的解决办法就是,仿照vantUI组件库的代码实现,重新采用微信自定义组件的形式重写,但是这样做工作量又上去了,比起使用uni-app来,这个不可行,工作量也好大呀!这个时候,我几乎又要放弃使用这个工具来转换了。那这里能不能换别的思路去解决呢?答案肯定是有的,前提就是了解wwto工具的代码实现过程以及思路:wwto是在转换的时候,通过修改原微信小程序的文件,那么我就能够仿照其思想在小程序运行时添加兼容的代码来让vantUI微信小程序组件库能够跑在支付宝小程序中,听起来是多么一件有趣的事
如何去做呢?通过查看了vantUI组件库的代码实现,是可以按这种思路实现的,大致需要修改组件库中两处代码
1、源代码basic.js 修改如下,主要是解决微信小程序triggerEvent api的功能,获取组件实例
let Behavior = p => p export const basic = Behavior({ methods: { $emit(...args) { let name = args[0]; let onPropsfn = this.props['on' + name[0].toUpperCase() + name.substring(1)]; // 可以正则匹配 data-*值 ['datadata-mm', 'data-', 'data-1'].filter(v => v.match(/^data-\w+/)) let index = this.data && this.data['data-index']; if (onPropsfn) { if (args.length == 1) { onPropsfn({detail: undefined}) } else if (args.length == 2) { onPropsfn({detail: args[1], currentTarget:{dataset: {index: index}}}) } else if (args.length >= 3) { onPropsfn.apply(this, args); } } // this.triggerEvent(...args); }, ... 省略 } }); 添加的代码实现:都是参考wwto实现的思路
2、源代码component.js 修改如下,主要是解决微信小程序中一系特性功能如:
externalClasses、properties、behaviors => 模拟到支付宝小程序中,如果有兴趣可以比对添加的代码,如何抹平这些特性差异,其中微信的relations组件特性,没法模拟,替代方案就只能用支付宝小程序相关组件了