uni-app + vant 开发支付宝小程序踩坑总结,持续更新中...
业务背景
- 项目最开始的目的只需要开发微信小程序,随着业务迭代,基本业务在微信小程序已经闭环成熟
- 现在突然需要支持支付宝小程序,给用户另一个平台的选择
- 领导指示:花最少的时间和成本(两周内,一个前端),迅速出一版支付宝的小程序
开始任务前的思考
- 之前的技术选型是 uni-app + vant 开发的微信小程序,迁移到支付宝有一定的可行性
- uni-app 虽然说是支持跨平台开发,但是不可能完全兼容,其中的坑肯定不少
- 组件库的支持情况如何?如果组件库无法支持那么开发成本回剧增
- 市面上有没有成熟的方案可以借鉴?
- 领导不愿意花额外更多的成本,但是又想要比较好的一个效果,在时间内的可行性有多大?
硬着头皮搞
尝试方案一
- uni-app 本身就是跨平台的,直接一行命令跑起来再说
yarn dev:mp-alipay - 好消息是vscode终端没有报错,编译出来了,坏消息是支付宝模拟器中报错
- 报错内容是xxx文件找不到,看了下编译产物中少了 'wxcomponents'这个文件夹
- 'wxcomponents'文件夹中放的就是 vant 的组件
- 检查page.json 中引用路径没有错,那就很奇怪
- 后面才知道需要把 'wxcomponents' 文件夹名称改为 'mycomponents' uni-app 文档中有说明
- 再次编译,支付宝模拟器依旧报错,看了下编译产物,有了 vant 组件,但是组件还是.vue文件,没有被编译成支付宝原生的文件
- 问题出在了公共组件没有被编译的问题上
思考
- 引用 vant 的方式是不是有问题?导致公共组件编译存在问题
- 全局在 main.js 中挂载或者当成普通的组件引入是否可行
按思考方案执行
一顿操作猛如虎,最后发现还是不行,但是知道问题所在了
vant 的组件库是 vant-weapp版本,是 vant 专门为开发微信小程序开发的,并不支持支付宝,这也是为什么组件中本身就有微信原生文件的原因**
尝试方案二
- 发现 vant 还有一个支付宝版的组件库 Vant-Aliapp
- 已经没人维护了,官网中的二维码体验也扫不出来了,有点子怕
- 拉取源码,把源码中的组件库抽出来,放到自己项目中的 mycomponents 文件夹中
- 改改相对路径,跑起来直接报错,原因是组件中还引用了 Antmove 的方法
- 因为这个组件是通过 Antmove 小程序转换器基于 Vant-Weapp 转换得到的
- 所以一定要把组件库上面一层的 ant_move文件引入才行
- 然后真的可以跑起来了,但是不出意外的话又要出意外了...
- 页面的样式崩了,还有很多报错
解决样式问题及报错问题
已经迈出第一步了,第二步应该会更容易 支付宝小程序会自动删除自定义组件标签上的任何class和style,对于组件上的样式需要使用custom-class 和 custom-style 这一阶段会涉及到改 vant 的源码,很快部分样式改好了,但是又发现一个问题:组件事件不生效 对组件源码进行 debugger 后,发现事件名称antmoveAction被转移之后就没有触发了,改写组件触发的方法,发现可以触发
更棘手的问题
但是 this 上面没有了$emit 方法,无法调用父组件的方法,在这里卡住了很久,改可以改,但是要把所有的组件全改了,那工作量太大了. 这个时候我又以为是公共组件挂载的问题,重新尝试将组件变成普通组件使用,但是还是不行.
在我快放弃的时候,我想起来把Vant-Aliapp这个项目跑起来看一下,虽然人家不是用 uni-app 开发的,但是可以借鉴一下 跑起来后发现他的事件响应是可以的,同时发现他的最外层也有一个 __antmove 文件.这说明他是将整个项目使用 antmove 进行转化而来的.那我也可以尝试一下
尝试方案三
- 首先使用 uni-app 打包出一份微信小程序的代码,然后使用 antmove 直接将代码转化为支付宝小程序代码
- 微信转支付宝方法文档
- 直接运行还是不行,因为文件夹名称以及样式还需要按上面的步骤走一遍
- 然后神奇的一幕到来了, 真的可以跑起来了,同时事件可以响应,当时我就乐了
细节问题解决
支付宝小程序不支持在组件上加 click touchmove 等事件
解决方案:在外层再套一层 view,事件直接响应在外层 dom 上
支付宝小程序不支持 .stop.prevent 事件修饰符
组件 v-show 不生效
解决方案:不影响的话可以使用v-if解决
icon 图标不显示或者现实异常
解决方案: icon组件中将class改成custom-class
van-radio 单选组件事件无法传递到 van-radio-group
解决方案: 自己改写一下 van-radio 源码,无需使用 van-radio-group 进行事件注入
// vant-radio 组件中的 onChange 方法改写
onChange(event) {
this.$emit('emitChange', this.data.name)
// this.emitChange(this.data.name)
}
tap 事件在 cell 组件无法使用
解决方案: 改用click
search 组件 clear 事件触发不了
解决方案: 需删除 vant-field 组件中的 focus 条件
tabbar 组件在 iphone13 机型中底部没有抬起
解决方案: 需要兼容新机型的判断条件,也可以重新写判断方法
// mixins 中 safe-area.js 文件中修改该函数
function getSafeArea() {
return new Promise((resolve, reject) => {
if (cache != null) {
resolve(cache)
} else {
_my.getSystemInfo({
success: ({ model, statusBarHeight }) => {
const deviceType = model.replace(/\s/g, '-')
// 新增 iPhone13|iPhone14|iPhone15 判断条件
const iphoneNew = /iphone-x|iPhone11|iPhone12|iPhone13|iPhone14|iPhone15/i.test(
deviceType
)
cache = {
isIPhoneX: iphoneNew,
statusBarHeight
}
resolve(cache)
},
fail: reject
})
}
})
}
date-time-picker 时间控件组件无法使用
原因: 支付宝小程序中不支持 selectComponent() 方法获取 dom 元素,但微信小程序是支持的
解决方案: 需自己手动改写,能够获取需要的 dom 元素,改动多个组件改动有点大,仅提供思路,在此不赘述
持续踩坑中...