小程序踩坑系列1

《小程序踩坑系列》会记录一些不值得大书特书的小程序相关问题(包括周边组件库)。

van-tabs 嵌入 van-popup 初始下划线显示不正常

vant-weapp 版本:^1.4.0

如果所示,刚打开的时候,下划线在最左边不正常的位置。

这个问题可以在 github 找到解决方法:https://github.com/youzan/vant-weapp/issues/2977

// 组件代码
lifetimes: {
  attached: function() {
    setTimeout(() => {
      this.selectComponent('#tabs').setLine()
      console.log(this.selectComponent('#tabs').setLine)
    }, 300)
  }
},

部分 iOS 版本按钮文字不显示

在某些版本的 iOS 中(比如 13.6。不过也有可能是手机自身的问题。),首次渲染视区之外的按钮,在滚动到显示的时候,其中的文字没有渲染出来。

解决方法是添加一个 css 属性:will-change: transform;

参考链接:ios下,一个弹窗中位于底部的button被加载的数据挤到首屏之下,而后按钮的文字颜色不渲染

上传代码失败

因为要对日期处理,所以引用了 dayjs 这个包。毕竟微信小程序官方文档说支持 npm。但在上传代码的时候报错了,大致是代码保护功能的问题。

解决方法有二:1. 去掉代码保护功能(在详情->本地设置里面)。2. 修改 npm 包,或直接拷贝源码到项目里。

getCurrentPages 为空数组

  1. 不要在 onLaunch 里获取,这时还没有页面。
  2. 不要在组件的 data 里赋值,这时也没有。可以在 attached 里获取。

van-canlendar 选择后格式化问题

给 van-canlendar 组件提供了格式化函数。但在 select 事件的回调函数里处理完选择的日期后,组件并没有按照预期正确格式化。比如,你需要对选中的日期标记,但是在触发 select 后,van-canlendar 还是用的上次的值。

// formatDate 无法使用 this,所以相关数据放这里
let selected = dayjs().format('YYYY-MM-DD')
let days = [] // 有宣教活动的日期

Page({
  /**
   * 页面的初始数据
   */
  data: {
    // 格式化日期
    formatDate: (day) => {
      // 选中
      if (dayjs(day.date).format('YYYY-MM-DD') === selected) {
        day.type = 'selected'
      } else {
        day.type = ''
      }
      // 标记
      if (days.includes(dayjs(day.date).format('YYYY-MM-DD'))) {
        day.bottomInfo = ' '
      }
      return day
    },
  },
}

为了解决这个问题,我重设了 formatDate,以此触发重新格式化。

// 选择日期
handleSelect(day) {
  selected = dayjs(day.detail).format('YYYY-MM-DD')
  // 因为 calendar 不会等回调完成后再格式化日期,所以先将格式化函数置空,设置好相关数据后再还原,以此触发重新格式化。
  let tempFormatter = this.data.formatDate
  this.setData({
    selected,
    selectedUnix: dayjs(selected).valueOf(),
    formatDate: null,
  })
  this.setData({
    formatDate: tempFormatter,
  })
},

van-popup 里的按钮多次点击触发

使用一个变量控制 van-popup 的显隐,点击里面的按钮就隐藏 van-popup,但多次点击还是会多次触发。可能是因为 van-popup 的显隐是动画,导致无法即时隐藏。所以还是需要用另外一个变量控制是否已经点击。

iOS 不支持 Promise.finally

安卓支持 Promise.finally,但 iOS 不支持。社区里一位开发者提供了解决方法:

// 在 app.js 的 onLaunch 里扩展
// https://developers.weixin.qq.com/community/develop/doc/000eea6c578e3808e5e7c429856c00
Promise.prototype.finally =function (callback) {
  let P =this.constructor;
  return this.then(
   value => P.resolve(callback()).then(() => value),
      reason => P.resolve(callback()).then(() => {throw reason })
  );
};

组件中使用 qrcode.js 不生效

因为 wx.createCanvasContext 在组件中需要手动传入 this,所以,调用 drawQrcode 时传入 this 就行了。其实 github 的文档里有写。

drawQrcode({
  width,
  height: width,
  canvasId: 'myQrcode',
  text: code,
  _this: this
})

小程序不打开调试无法请求接口

问题:体验版小程序无法请求接口,但打开调试模式就可以正常请求。

  1. 微信小程序后台没有加入 request 域名.
  2. 使用了端口号,但协议用的 https。使用端口号的情况下要用 http。并且需要打开调试模式,不校验域名。
  3. 没有使用端口号,但是使用了 http 协议。

总结:非 https 模式需要打开调试模式,并且不校验域名。

iOS 按钮 1rpx 边框不显示

在部分 iOS 设备上,当设置按钮边框为 1rpx 的时候会出现不显示的问题。因为不足 1 个物理像素的话,在 iOS 会进行四舍五入,而安卓好像统一向上取整,这也是上面两种设备表现不同的原因。

网上有很多解决方案,用行内式、设置父元素尺寸、用 transform: scale() 缩放……但都不优雅。后来在一个帖子里找到了足够简单优雅的方案:

transform: rotateZ(360deg)

van-checkbox 二次渲染不生效

van-checkbox 根据列表渲染,但是在重新获取列表并设置新的 value 后,van-checkbox 列表更新了,但新的列表没有根据 value 呈现选中状态,并且点击切换无效。

解决方法:更新列表前先清空列表,用到 van-checkbox 的部分用 wx:if 强制重新渲染。

input 输入时文字错位

解决:页面容器不要设置高度 100%,改成 height: auto。