优秀的编程知识分享平台

网站首页 > 技术文章 正文

uni-app实现图片上传组件(uniapp多张图片上传)

nanyue 2024-08-03 18:10:07 技术文章 8 ℃

实例简介

本例分享图片上传组件的实现过程,并实现下面可配置的参数:

1、maxLength图片最大上传数量;

2、maxSize单文件大小限制;

3、allowTypes文件类型限制;

并实现图片预览和图片删除方法等。

功能实现

1、组件搜索(uni-img-upload)实现代码

01 template代码

<template>
  <view class="group-images">
    <view class="image-box" v-for="(item, index) in images" :key="item.id">
      <image class="upload-imgs" :class="item.loaded?'show':''" :src="item.url" mode="aspectFill" :data-id="item.id" :data-index="index"
        @click="imagePreview" @load="endLoading" @error="endLoading">
      </image>
      <button class="img-loading" loading v-if="!item.loaded"></button>
      <text class="del-t" :data-index="index" @click="delImage">删除图片</text>
    </view>
    <view class="addImage" @click="chooseGroupImage" v-if="images.length < maxLength"></view>
  </view>
</template>

02 script代码

<script>
  export default {
    name: "uni-img-upload",
    props: {
      // 最大上传数量
      maxLength: {
        type: Number,
        default: 1
      },
      // 单文件大小限制,默认 1M
      maxSize: {
        type: Number,
        default: 1024
      },
      // 文件类型限制
      allowTypes: {
        type: String,
        default: 'JPG,JPEG,PNG,BMP'
      }
    },
    data() {
      return {
        images: []
      }
    },
    methods: {
      // 选择图片
      chooseGroupImage: function(event) {
        let that = this;
        let imgs = this.images;
        if (imgs.length >= this.maxLength) return;
        let max = this.maxLength - this.images.length;
        uni.chooseImage({
          count: max,
          sizeType: ['compressed'], // 压缩图
          sourceType: ['album', 'camera'], // 相册 / 相机
          success(res) {
            if (!that.checkImgType(res.tempFiles)) return;
            if (!that.checkImgSize(res.tempFiles)) return;
            // 开始上传图片,uploadImgs 中会结束 loading
            uni.showLoading({
              title: '上传图片中...',
              mask: true
            });
            that.uploadImgs(res.tempFiles);
          }
        });
      },
      // 上传图片(如果是调用接口,可在此修改)
      uploadImgs: function(imgs, index = 0) {
        let images = this.images;
        imgs.map((item, index) => {
          images.push({
            id: index,
            url: item.path
          });
        });
        this.images = images;
        uni.hideLoading();
      },
      // 检查图片类型
      checkImgType: function(imgs) {
        const allowTypes = this.allowTypes.toUpperCase();
        for (let i = 0; i < imgs.length; i++) {
          let item = imgs[i];
          let type = item.name.slice(item.name.lastIndexOf('.') + 1);
          type = type ? type.toUpperCase() : ',,';
          if (allowTypes.indexOf(type) < 0) {
            uni.showToast({
              title: '请上传 ' + this.allowTypes + ' 格式图片',
              icon: 'none',
              duration: 2000
            });
            return false;
          }
        }
        return true;
      },
      // 检查图片大小
      checkImgSize: function(imgs) {
        for (let i = 0; i < imgs.length; i++) {
          let item = imgs[i];
          if (item.size / 1024 > this.maxSize) {
            let info = '';
            if (this.maxSize > 1024) info = (Math.floor(this.maxSize / 1024 * 100) / 100) + 'M';
            else info = this.maxSize + 'KB';
            uni.showToast({
              title: '图片大小超出限制(' + info + ')',
              icon: 'none',
              duration: 2000
            });
            return false;
          }
        }
        return true;
      },
      // 删除图片
      delImage: function(event) {
        let index = event.currentTarget.dataset.index;
        let images = this.images;
        images.splice(index, 1); // 删掉点击的图片
        this.images = images;
      },
      // 图片预览
      imagePreview: function(event) {
        if (this.disabled) return;
        let index = event.currentTarget.dataset.index;
        let images = this.images;
        let imgUrls = [];
        images.map(item => imgUrls.push(item.url));
        uni.previewImage({
          current: imgUrls[index], // 当前显示图片的http链接
          urls: imgUrls // 需要预览的图片http链接列表
        });
      },
      // 图片加载结束事件
      endLoading: function(event) {
        let ii = event.currentTarget.dataset.index;
        let id = event.currentTarget.dataset.id;
        // 删除操作后仍然会触发此事件,使用 id 做对比
        if (!this.images[ii] || this.images[ii].id !== id) return;
        this.$set(this.images[ii], 'loaded', true);
      }
    }
  }
</script>

03 style代码

<style lang="less" scoped>
  .group-images {
    margin: 0 50rpx;
    .image-box {
      display: inline-block;
      width: 140rpx;
      height: 140rpx;
      position: relative;
      margin-right: 30rpx;
      margin-bottom: 20rpx;
      &:nth-child(4n) {
        margin-right: 0;
      }
      .upload-imgs {
        width: 140rpx;
        height: 140rpx;
        border-radius: 8rpx;
        opacity: 0;
        transition: opacity 1s;
        &.show{
          opacity: 1;
        }
      }
      .img-loading {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 40rpx !important;
        height: 40rpx !important;
        padding: 0 !important;
        line-height: 40rpx !important;
        background-color: transparent;
        border: none;
        &::after{
          border: none;
        }
      }
      .del-t {
        position: absolute;
        bottom: 0;
        left: 0;
        font-size: 26rpx;
        background-color: rgba(204, 204, 204, 0.6);
        width: 100%;
        text-align: center;
        padding: 6rpx 0;
      }
    }
    .addImage {
      display: inline-block;
      color: #3d7af5;
      font-size: 100rpx;
      border: 2rpx solid #e5e5e5;
      width: 136rpx;
      height: 136rpx;
      text-align: center;
      overflow: hidden;
      border-radius: 8rpx;
      position: relative;
      &::before {
        content: '';
        display: block;
        position: absolute;
        background: #ed292a;
        width: 50rpx;
        height: 6rpx;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        border-radius: 6rpx;
      }
      &::after {
        content: '';
        display: block;
        position: absolute;
        background: #ed292a;
        width: 6rpx;
        height: 50rpx;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        border-radius: 6rpx;
      }
    }
  }
</style>

2、页面引用组件

Tips:可根据需要自行配置参数

<template>
  <view>
    <uni-img-upload ref="progressImgs" :max-length="5"></uni-img-upload>
  </view>
</template>

<script>
  import uniImgUpload from '../../components/uni-img-upload/uni-img-upload';
  export default {
    data() {
      return {

      }
    },
    onLoad() {

    },
    methods: {

    }
  }
</script>

<style lang="less" scoped>
</style>

Tags:

最近发表
标签列表