那些年做小程序遇到的问题


之前做过一年的小程序,期间碰到了很多问题,这里做一个总结,很多问题,不知道微信有没有去解决。这里只是做一个简单明了的记录。

一、看图片和选择图片确定之后触发onshow的bug

解决方法如下: 1.data或者全局里面定义一个变量

data: {
    notShow: false
}

2.onshow事件最上面中添加下面代码,如果notshow为true,就直接return,不触发onshow里面的其他代码

onShow() {
    if (this.notShow) {
        this.setData({ notShow: false });
        return;
    }
}

3.在wx.previewImage或者wx.chooseImage事件调用之前插入下面代码,这样在执行onShow事件的时候,就会直接跳出来,不触发其他代码

this.setData({ notShow: true})

二、微信上传线程突破九个限制

很多时候我们我们上传直接用的Promise.all微信一次只能发9个请求,所以上传图片最多只能是9个图片。Promise.all 方法会同时运行多个promise对象,想要突破限制,核心思想就是顺序请求

1.在一个请求完之后在顺序执行下一个请求,定义方法如下:

//顺序处理
sequenceTasks(tasks) {
    function recordValue(results, value) {
        results.push(value);
        return results;
    }
    var pushValue = recordValue.bind(null, []);
    return tasks.reduce(function (promise, task) {
        return promise.then(task).then(pushValue);
    }, Promise.resolve());
}

2.接着定义上传图片的方法,把每个上传图片都变成promise形式:

//图片promise
uploadImage(file) {
    return function() {
        return new Promise((resolve, reject) => {
            wx.uploadFile({
                //图片服务器
                url: uploadFileServerApi,
                filePath: file,
                success (res) {
                    resolve({
                        name: res.name,
                        path: res.path
                    });
                },
                fail (err) {
                    reject(err)
                }
            })
        });
    }
}

3.在需要上传图片的地方添加如下代码,

// 图片上传方法
let promiseArr = [];
//把每个图片path编程promise形式
for (let i = 0; i < len; i++) {
    let promise = this.uploadImage(imageList[i]);
    promiseArr.push(promise)
}
sequenceTasks(promiseArr).then((result)=> {
   //处理result
})

三、bindInput卡顿

在小程序里面有bindInput方法,在输入框内容变化触发,一般在一边会定义方法把输入的文字放到data里面:

bindInput(e){
    this.setData({ textContent: e.detail.value })
}

小程序里面频繁setData就会造成卡顿,使用bindBlur失去焦点的时候再去setData,就不需要频繁去setData造成卡顿。

四、”invokeWebviewMethod 数据传输长度为 xxx 已经超过最大长度 1048576”问题解决

上拉加载数据,一直往data里面塞数据,最后就会报错。

data:{
    list: []
}

可以利用子集list里面包含很多个子数组

function safeRender(res) {
    let d = {}
    let l = `list[${pageIndex}]`
    d[l] = res
    this.setData(d)
}

wxml如下:

<view wx:for="" wx:for-index="index">
  <view class="content" wx:for=""></view>
</view>

五、textarea原生实现,总是浮动在最上层

解决方法有两个 1.直接暴力隐藏textarea,这个比较简单,但是用户体验可能比较差 2.使用替代元素,一个用于用户输入,一个用于展示,代码如下:

<!-- 用户输入的textarea组件 -->
<textarea id="text-area" value="" bindinput='txtInput' wx:if="" />
<!-- 用于展示的textarea组件 -->
<view class='rich-text' style="" wx:else>
  <rich-text nodes=""></rich-text>
</view>

换行符需要特殊处理:

textareaContent.replace(/\n/g, '<br/>')

六、canvas原生实现,总是浮动在最上层

在做项目的过程中遇到了使用使用canvas画二维码的时候,二维码画出来之后,滑动的时候会浮动在上层,解决办法如下: 1.data里面定义二维码路径

data: {
    QRImgUrl: '',//二维码图片路径
}

2.添加一个将二维码导出生成图片,并返回文件路径的方法:

saveCanvas() {
  wx.canvasToTempFilePath({
    canvasId: 'qr-code',
    success: (res) => {
      this.setData({
        QRImgUrl: res.tempFilePath
      })
    }
  })
}

3.最后在调用draw之后(即绘制画布的方法),调用saveCanvas:

setTimeout(() => {
    this.saveCanvas()
}, 1000);

注:这里的setTimeout一定要加如果画布没绘制完图片路径导出来就是空的。 经过手头的测试机测试,ios和模拟器在1000ms的情况下都可以显示,部分安卓机3000ms才显示,部分安卓机画了3000ms也显示不出来。。。 推荐使用wx.createCanvasContext(canvasId, this),这个的draw方法是带有回调函数的,这样也不用setTimeout了,直接在回调成功的情况下,再调用wx.canvasToTempFilePath就可以了。

参考:

https://www.kancloud.cn/kancloud/promises-book/44249

https://developers.weixin.qq.com/blogdetail?action=get_post_info&docid=000222e78f0d38e3552636d5056804&token=16804411&lang=zh_CN

https://developers.weixin.qq.com/blogdetail?action=get_post_info&docid=0008ec49d849681c05866d9a957008&highline=input%20setData

https://juejin.im/post/5b6ab1f951882539766ea558