小程序多图上传的优化解决方案

根据我实际开发的经验造了一个多图上传的轮子,可直接拿来复用

Posted by 陈剑 on February 7, 2018

正所谓前人栽树,后人乘凉。

经常看到开发群里有人咨询多图上传的问题

恰好我在项目开发中优化、解决了多图上传的若干问题

前言

微信小程序是发布还不到一年并仍处于试验期的产物,故很多API以及轮子都不完善,本人在实际项目开发中将遇到的问题都进行了解决、优化,如多列选择、跨页面传对象数组等等,并将其开源出来。

平时有时间我会将这些问题及解决方法整理为文档发上来,今天先总结一个很多人都问我的问题,即如何进行多图上传?

图片上传微信已经给出了现成的API,但是在实际开发中远远不够,例如多图上传时会因为图片大小不同存在网络延迟,导致最终上传的顺序和用户最初选择图片的顺序不一致,以及如何对已经上传的多张图片进行删除操作?这些细小但却会影响实际开发合用户体验的问题困扰了很多初入门的开发者,今天我将我实际项目中的多图上传功能进行代码逻辑解析,以方便各位开发者复用。

最终实现效果

支持最多上传9张图片,上传方式可分为“相机拍摄”和“图库选择”,每张图片右上角均有删除标识,可对其进行删除操作。

### 前端页面实现

<view class="tip-photo" style='margin:40rpx 0rpx 40rpx 0rpx;'>相关证书</view>
  <view class="gallery">
    <view class="item" wx:for="" >
      <image class="thumb" data-current=""  style="width: rpx; height: rpx" src=""  bindtap="previewImage"/>
      <image class="delete" src="../../image/deleteImage.png" data-index="" bindtap="delete"></image>
    </view>
  <image class="thumb" style="width: rpx; height: rpx" src="../../image/upload.png"  bindtap="upImg"/>
</view>

首先点击thumb触发upImg事件,从而进行图片的选择及上传,同时需要将上传成功的图片刷新至页面,即先将图片地址以数组的形式存入urlArr,并由item对其进行for循环刷新至页面。

此时我们需要注意,需要到不同手机屏幕适配的问题,要保证刷新出的图片恰好自适应大小并一列显示四个,此时我们需要先获取到本机的屏幕宽度,并对其进行四分

image_width: getApp().screenWidth / 4 - 10,

作为容错和边距还需再减去10rpx,于是每张图片的宽度为计算后的image_width。

将delete固定在每张图片右上角,并用index标记,从而在点击时出发点击事件,并将index传回识别点击的是第几张图片。

图片拍摄、选择js逻辑

upImg: function () {
    var that = this;
    wx.chooseImage({
      count: 9, // 默认9
      sizeType: ['compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function (res) {
        wx.showNavigationBarLoading()
        that.setData({
          loading: false
        })
        var urlArr = that.data.urlArr;
        // var urlArr={};
        var tempFilePaths = res.tempFilePaths;
        var images = that.data.images;
        that.setData({
          images: images.concat(tempFilePaths)
        });
        var imgLength = tempFilePaths.length;
        if (imgLength > 0) {
          var newDate = new Date();
          var newDateStr = newDate.toLocaleDateString();
          var j = 0;
          //如果想顺序变更,可以for (var i = imgLength; i > 0; i--)
          for (var i = 0; i < imgLength; i++) {
            var tempFilePath = [tempFilePaths[i]];
            var extension = /\.([^.]*)$/.exec(tempFilePath[0]);
            if (extension) {
              extension = extension[1].toLowerCase();
            }
            var name = newDateStr + "." + extension;//上传的图片的别名      
            var file = new Bmob.File(name, tempFilePath);
            file.save().then(function (res) {
              wx.hideNavigationBarLoading()
              var url = res.url();
              console.log("第" + i + "张Url" + url);
              urlArr.push({ url });
              j++;
              console.log(j, imgLength);
              // if (imgLength == j) {
              //   console.log(imgLength, urlArr);
              //如果担心网络延时问题,可以去掉这几行注释,就是全部上传完成后显示。
              // showPic(urlArr, that)
              that.setData({
                urlArr: urlArr,
                loading: true
              });
              // }
            }, function (error) {
              console.log(error)
            });
          }
        }
      }
    })
    console.log(that.data.urlArr)
  },

wx.chooseImage是微信提供的图片上传api,而我们依然需要对其进行优化更改。

首先需要在一开始引入wx.showNavigationBarLoading()并将loadingb变量赋值false,从而保证在上传时给用户提示避免打断传输。

然后初始化变量urlArr赋值为that.data.urlArr,注意这里考虑到用户可能不会一次选择上传全部的图片,可能会上传一张,退出后再上传两张,故不可在事件启动时将其赋空值。

待图片上传成功后将其url地址push至urlArr,待全部上传完后将loading赋值为true即可。

图片删除js逻辑

 delete: function (e) {
    // 获取本地显示的图片数组
    var index = e.currentTarget.dataset.index;
    var images = that.data.images;
    var urlArr = that.data.urlArr;
    urlArr.splice(index, 1);
    images.splice(index, 1);
    that.setData({
      images: images,
      urlArr: urlArr
    });
    console.log(that.data.urlArr)
  }
})

函数变量传入e后,由e.currentTarget.dataset.index可获知用户点击了第几张图片,然后分别使用splice对urlArr和images数组进行删除,并重新赋值。

图片预览js逻辑

 previewImage: function (e) {
    var current = e.currentTarget.dataset.current;
    wx.previewImage({
      current: current, // 当前显示图片的http链接
      urls: that.data.images // 需要预览的图片http链接列表
    })
  },

在点击相应图片时进行预览,依然是传入e后获取点击点击的第几张图片,然后调用wx.previewImage传入图片url地址即可。