用uview-plus和Vueuse封装一个图片上传组件

49 阅读2分钟

先上效果和使用方法

效果.png

<template>
  <ImgUploader :fileList="fileList" />
</template>

<script setup>
import ImgUploader from "@/pages/components/ImgUploader.vue";
const fileList = ref([]);
</script>

嘎嘎简便,上源码,注释里有详细说明,更具体的属性请查阅下面的链接

uiadmin.net/uview-plus/…

<template>
  <u-upload
    :fileList="fileList"
    @afterRead="afterRead"
    @delete="deletePic"
    name="pic"
    :previewFullImage="true"
    :width="width"
    :height="height"
  ></u-upload>
</template>

<script setup>
import { upload } from "@/apis/systemRequest";
import { useVModel } from "@vueuse/core";
/// fileList参数(数组,元素为对象),显示预置的图片。其中元素的url属性为图片路径
const props = defineProps({
  fileList: {
    type: Array,
    default: () => {
      return [];
    },
  },
  width: {
    type: Number,
    default: 220,
  },
  height: {
    type: Number,
    default: 220,
  },
});
const emit = defineEmits(["update:fileList"]);
const fileList = useVModel(props, "fileList", emit);
/**
 * @function 删除图片
 */
const deletePic = (event) => {
  fileList.value.splice(event.index, 1);
};
/**
 * @function  读取图片后的处理函数
 */
const afterRead = async (event) => {
  /// 当设置 multiple(是否可以多选图片) 为 true 时, file 为数组格式,否则为对象格式
  let lists = [].concat(event.file); ///统一为数组格式
  let fileListLen = fileList.value.length; ///即将插入图片所在的下标
  ///上传前是loading状态
  lists.map((item) => {
    fileList.value.push({
      ...item,
      status: "uploading",
      message: "上传中",
    });
  });
  for (let i = 0; i < lists.length; i++) {
    try {
      const result = await uploadFilePromise(lists[i]); ///进行网络请求
      ///成功后将loading状态变为success
      let item = fileList.value[fileListLen];
      fileList.value.splice(fileListLen, 1, {
        ...item,
        status: "success",
        message: "",
        webUrl: result.data.data.url, //! 这里要根据接口返回的数据格式来定制
      });
      fileListLen++;
    } catch (error) {}
  }
};
/**
 * @function 处理文件并进行网络请求
 */
async function uploadFilePromise(file) {
  let formData = new FormData(); /// 传递二进制必须使用formdata格式
  let response = await fetch(file.url); /// 用fetch请求临时的blob地址
  let blob = await response.blob(); /// 将其转为blob格式,再转为file,以组装到formData
  formData.append("file", new File([blob], file.name, { type: file.type }));
  try {
    const res = await upload(formData);
    if (res.data.msg === "success") {
      //! 这里要根据接口返回的数据格式来定制
      return res;
    } else {
      uni.showToast({
        title: res.data.msg, /// 显示报错的内容
        icon: "error",
      });
    }
    throw res.data;
  } finally {
  }
}
</script>

<style lang="scss" scoped>
:deep(.u-upload__button) {
  background-color: white;
  border: 1px solid rgb(185, 178, 178);
  .u-icon__icon {
    font-size: 90rpx !important;
  }
}

:deep(.u-upload__wrap__preview) {
  border: 1px solid rgb(185, 178, 178);
  .uicon-close {
    font-size: 30rpx !important;
  }
}

:deep(.u-upload__wrap) {
  padding-left: 8px;
  padding-top: 8px;
}
</style>