uni-app + vant 开发支付宝小程序踩坑总结,持续更新中...

1,704 阅读4分钟

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 进行转化而来的.那我也可以尝试一下

尝试方案三

image.png

  • 首先使用 uni-app 打包出一份微信小程序的代码,然后使用 antmove 直接将代码转化为支付宝小程序代码
  • 微信转支付宝方法文档
  • 直接运行还是不行,因为文件夹名称以及样式还需要按上面的步骤走一遍
  • 然后神奇的一幕到来了, 真的可以跑起来了,同时事件可以响应,当时我就乐了

细节问题解决

支付宝小程序不支持在组件上加 click touchmove 等事件

解决方案:在外层再套一层 view,事件直接响应在外层 dom 上

支付宝小程序不支持 .stop.prevent 事件修饰符
组件 v-show 不生效

解决方案:不影响的话可以使用v-if解决

image.png

icon 图标不显示或者现实异常

解决方案: icon组件中将class改成custom-class

image.png

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 条件

image.png

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 元素,改动多个组件改动有点大,仅提供思路,在此不赘述


持续踩坑中...