1:目前市场上微信小程序比较成熟,并且有自主研发的开发工具,支付宝小程序相对来说这块要弱一点。
用微信开发工具:微信web开发者工具 开发好的小程序 可以在VS Code上直接转换为 支付宝小程序
转换过程:
请按照以下姿势操作:
前往/download 下载 VS code(注意 VS code != 宇宙第一大 IDE visual studio,不要弄错);
启动 VS code 并选择『扩展』,搜索 “小程序助手”并安装;
重启 VS code ,然后打开已有小程序项目源码。选中 app.json 并单击右键,从弹出的菜单中选择『转换小程序』。针对一般小程序,这个转换过程约 1-3s;
转换完成后,检查 VS code 顶部信息条上的反馈,并根据其指示来进一步手工完善代码;
详细介绍
app.json 转换
app.json文件为整个小程序配置文件,不过微信小程序app.json和支付宝小程序在app.json配置文件支持的能力不完全一致,部分一致的但名称不一致的配置,转换工具会分析并转换出来。
转换出来后错误报告:
转换之后需要注意几点:
1:转换如果报错,需要手动添加一个文件:在根目录下:
Behavior.js
里面的内容是:
const wx2my = require('./wx2my');
const Behavior = require('./Behavior');
// Create by wx2my.
module.exports = function Behavior(obj) {
const keyMap = {
properties: 'props',
created: 'onInit',
attached: 'didMount',
detached: 'didUnmount'
};
Object.keys(keyMap).forEach(key => {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj[keyMap[key]] = obj[key];
delete obj[key];
}
}); // if exist lifetimes replace others.
if (obj.lifetimes) {
const keyMap = {
created: 'onInit',
attached: 'didMount',
detached: 'didUnmount'
};
const lifetimesObj = obj.lifetimes;
Object.keys(keyMap).forEach(key => {
if (Object.prototype.hasOwnProperty.call(lifetimesObj, key)) {
obj[keyMap[key]] = lifetimesObj[key];
}
});
delete obj.lifetimes;
}
return obj;
};
2:下载支付宝小程序后,需要在支付宝的小程序每一个js的内容上添加这样的引用
const wx2my = require('../wx2my');
const Behavior = require('../Behavior');
3:支付宝添加js引用跟微信有一些区别,需要主要的是要在前面加 ../
4:需要重新调整样式
在支付宝里面的样式跟微信的完全不一样,需要调整rem的大小。
5:支付宝小程序目前对用户自定义控件兼容性不是非常友好,需要注意这点,尽量减少或者不用自定义控件。
6:支付宝申请小程序跟发布版本基本上跟微信小程序一致,需要注意一点,支付宝小程序发布审核需要2个工作日,微信小程序只需要几个小时。
7:支付宝小程序页面js一样有缓存。缓存更新时间跟微信差不多,一个工作日
转换方式:
navigationBarTitleText -->defaultTitle**
enablePullDownRefresh -->pullRefresh**
navigationBarBackgroundColor -->titleBarColor**
...等
其中微信小程序支持,支付宝小程序不支持的,需要开发者自己手动修改,如:networkTimeout、functionalPages、workers等
全局组件转换
微信小程序支持全局组件,即在app.json中添加usingComponents字段,这样在小程序内的页面或自定义组件中可以直接使用全局组件而无需再声明。
转换方式: 转换工具会分析小程序中所有页面和组件,找到那些使用了全局组件的页面和组件,并把全局组件声明在页面或组件的json文件中,当做普通组件引用和使用。同时把全局组件的声明删除。
wxml文件转换
转换逻辑是以wx:xxx开头的,替换为a:xxx方式。
a. 事件相关的转换,微信中 bindeventname **或 bind:eventname** 转换为 onEventname, 如下:
转换前:
<page
bindtap="showName"
bind:input = "actionName"
catchchange="catchchange"
bindtouchend="onTouchEnd"
></page>
转换后:
<page
onTap="showName"
onInput = "actionName"
catchChange="catchchange"
onTouchEnd="onTouchEnd"
></page>
b: 循环语句转换, 如下:
转换前:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName" wx:key="unique">
{{idx}}: {{itemName.message}}
</view>
转换后:
<view a:for="{{array}}" a:for-index="idx" a:for-item="itemName" a:key="unique">
{{idx}}: {{itemName.message}}
</view>
c: wxs代码转换,微信小程序中的wxs功能对应支付宝小程序中的sjs功能,微信wxml中支持引用外部wxs文件和内联wxs代码,支付宝中只支持引用外部文件方式使用sjs,不支持内联sjs代码。
转换方式:转换工具分享所有wxml文件,找到wxs内联代码,提取wxs的内联代码,生成sjs文件,并使用外部引用的方式引入sjs文件,如下:
转换前:
<wxs src="../wxs/utils.wxs" module="utils" />
<wxs src="../wxs/utils.wxs" module="utils"> </wxs>
<wxs module="parse">
module.exports.getMax = getMax;
</wxs>
转换后:
<import-sjs from="../wxs/utils.sjs" name="utils" />
<import-sjs from="../wxs/utils.sjs" name="utils"/>
<import-sjs from="./parse.sjs" name="sjsTest" />
并在同级目录下创建了 parse.sjs 文件,并转换wxs的CommonJS为ESM
parse.sjs文件内容:
export default { getMax };
d: 无法替换完成的,在转换后的支付宝小程序的代码中,插入注释代码,提醒开发者并需要开发者手动检查修改。如下:
转换前:
<cover-image
class="img"
src="/path/to/icon_play"
bindload="bindload"
binderror="binderror"
aria-role="xxx"
aria-label="xxx"
/>
转换后:
<cover-image
class="img"
src="/path/to/icon_play"
bindload="bindload"
binderror="binderror"
aria-role="xxx"
aria-label="xxx"
/><!-- WX2MY: 属性bindload、binderror、aria-role、aria-label不被支持,请调整 -->
出现这种情况,开发者可以手动的搜索 WX2MY: 关键字,查找需要修改的代码
js文件转换
转换工具对api相关的调用转换使用了桥接文件 wx2my.js ,在所有js文件顶部引入wx2my.js文件,对api的调用,使用桥接函数,桥接函数对api参数不一致的地方在函数内部进行处理,如下:
转换前:
wx.request(opts)
转换后:
wx2my.request(opts)
wx 转换为 wx2my ,其中wx2my为前进函数对外的方法
桥接函数中 request 的方法如下:
{
request: function request({ url, data, header, method, success, fail, complete, }) {
const requestObj = {
url,
headers: header,
method,
data: JSON.stringify(data),
dataType,
success: ({ data, status, headers }) => {
if (success) {
success({ data, statusCode: status, header: headers });
}
},
fail,
complete,
};
return my.request(requestObj);
}
}