在蚂蚁金服的开放平台上看到一些贴子,说提供一个工具,一键转换微信小程序为支付宝小程序。我与百度的人交流时,也听到相似的东西。其实都没有这么简单,它们最多是将一些循环条件分支指令改一下名,将一些文件的后缀名改一下,更多的差异点在API与各式的配置对象上,细节是魔鬼,我在娜娜奇的官网也列举了许多相关的东西,但也不能打票说已经很齐全。。。。
各种小程序的差异点-文档
补充一句,娜娜奇是我们公司的小程序开发框架,以React方式转译成各种小程序与快应用的框架。类似于京东的taro。
最近忙于支付宝小程序的开发,我得到许多有关小程序的一手资料,包括自己测试得到的,及从百度,小米快应用与支付宝内部人士提供的。
本文将重点说一下小程序的组件机制,之前娜娜奇的组件机制是基于template标签实现的,但百度的template有点BUG,给他们提了,不知现在修了没有。与template机制在快应用又出入太大,于是转向用自定义组件机制开发娜娜奇的组件机制。下面链接有一些相关的测试与说明
转换小程序 · Issue #133 · RubyLouvre/anu
经测试,使用了自定义组件机制的确是比template实现的简洁一些。但自定义组件机制是一个比较高级的特性,因此兼容性上比template差多了。只能内部推到各方改进了。
微信在Component的配置对象提供了一些对象如methods, lifetimes,pageLifetimes,来减少其直辖的配置项。
比如说lifetimes收纳了created、attached、ready、moved、detached这些生命周期钩子,pageLifetimes收纳了onShow, onHide这些与页面切换的钩子,methods收纳剩下的方法,另外还有许多配置项。的确,微信小程序独自发布这么久,肯定是最完善的
支付宝的自定义组件机制没有properties,只有props,并且作用也不一样,props只是指定默认值,不是规定参数类型。支付宝也没有lifetimes与pageLifetimes对象,生命周期函数的名字也不一样 didMount 、didUpdate 、didUnmount,数量也少了,但从名称来看,支付宝在内部应该运行一个自己的迷你React。
其他方面,支付宝没有 dataset, selectComponent,selectAllComponents,getRelationNodes这些东西,但支持了早被React废弃的mixin机制。
支付宝没有created这样的钩子是相当麻烦的事,因此积级推动他们加上这个钩子!
百度的自定义组件机制与微信的较为相近,但也没有lifetimes与pageLifetimes对象,只有4种生命周期钩子:created,attached,ready,detached。有selectComponent,selectAllComponents。
快应用的页面与组件的配置对象都是一样,但它没有构造函数,只是要求我们export一个对象
有props对象,用来定义类型与默认值,也有与state相似的data对象,也有三个做了访问限制的private, protected, public对象。生命周期钩子上有onInit、onReady、onDestroy这三个。
从组件的设计来看, 微信 > 百度 > 支付宝 > 快应用
因此想兼容这么多种小程序,我们必须自己写一个工厂方法,根据不同的平台生成不同的配置项,并且放弃掉一些微信的强大功能了。
var hooksName = { wx: ['created', 'attached', 'detached'], bu: ['created', 'attached', 'detached'], ali: ['didMount', 'didMount', 'didUnmount'], quick: ['onInit', 'onReady', 'onDestroy'], }; export function registerComponent(type, name) { registerComponents[name] = type; var reactInstances = (type.reactInstances = []); var wxInstances = (type.wxInstances = []); var hooks = [ function created() { var instance = reactInstances.shift(); if (instance) { console.log('created时为', name, '添加wx'); instance.wx = this; this.reactInstance = instance; } else { console.log('created时为', name, '没有对应react实例'); wxInstances.push(this); } }, function attached() { if(appType == "ali"){ created.call(this) } if (this.reactInstance) { updateMiniApp(this.reactInstance); console.log('attached时更新', name); } else { console.log('attached时无法更新', name); } }, function detached() { this.reactInstance = null; }, ]; var data = { props: {}, state: {}, context: {}, }; var config = { data: data, public: data, dispatchEvent: eventSystem.dispatchEvent, methods: { dispatchEvent: eventSystem.dispatchEvent, }, }; hooksName[appType].forEach(function(name, index) { config[name] = hooks[index]; }); return config; } |