Ant-Design-Vue 图片上传

功能演示

我们要实现的功能如下,有两个按钮,点击第一个按钮选择文件,选择文件后点击第二个按钮上传到服务器。

功能需求:

  1. 只允许上传 pngjpg/jpeg 格式的图片

  2. 没有上传图片时显示占位图

  3. 选择完图片后在页面中渲染出来

构建页面

template

<template>
  <div>
    <div>
      <!-- 选择图片后展示待上传的图片 -->
      <img v-if="base64img" :src="base64img" />
      <!-- ↓ 没有选择时显示占位图 -->
      <img v-else="base64img" src="@/assets/placeholderImg.png" />
    </div>

    <!-- 限制最大待上传的文件数量为 1 -->
    <!-- 添加选择文件后的回调和移除待上传文件的回调 -->
    <a-upload :before-upload="beforeUpload" :max-count="1" @remove="handleRemove">
      <a-button>
        <upload-outlined></upload-outlined>
        Select File
      </a-button>
    </a-upload>
    <!-- 点击上传按钮 -->
    <a-button @click="triggerUpload" :loading="btnLoading">上传</a-button>
  </div>

逻辑部分

TypeScript

import { UploadOutlined } from '@ant-design/icons-vue'
import fruitApi from "@/api/fruitApi";
import {ref} from "vue";
import {Upload} from "ant-design-vue";
import {Notice} from "@/utils/interfaces";

const fileList = ref();
// ↑ 待上传文件列表 (其实里面也就能放一个文件)
const base64img = ref();
// ↑ 我们在页面中显示待上传的图片的原理是
// 将所选择的本地图片转换为 Base64 编码
// 之后让图片的 src = base64img 来实现的
// 所以 base64img 就是一个储存图片编码的字符串
const btnLoading = ref<boolean>(false);
// ↑ 上传按钮的 loading 状态
// 在点击上传 至 获取服务器回调的时间内 按钮不可用

/**
 * 对图片编码的函数
 */
function getBase64(img: Blob, callback: (base64Url: string) => void) {
  const reader = new FileReader();
  reader.addEventListener('load', () => callback(<string>reader.result));
  // ↑ 监听 reader 的 load 事件,触发时执行回调函数
  // 回调函数的作用就是将图片编码的base64字符串传给 base64img
  reader.readAsDataURL(img);
}

/**
 * andv 上传文件的回调
 * 返回 false 则不会上传文件,而是由我们手动上传
 * 返回 Upload.LIST_IGNORE 会取消将文件添加至待上传列表
 * @param file 所选择的文件
 */
function beforeUpload(file: any) {
  console.log(file);
  // 判断文件是否为图片格式
  const isImg = (file.type === 'image/jpeg' || file.type === 'image/png');

  // 如果文件不是图片格式则禁止上传
  if (!isImg) {
    Notice.error("只能上传 jpeg/jpg/png 格式的文件!");
    // ↑ Notice.error 是我自己写的 Notice 类的一个静态函数
    // 用的是 antdv 的 Notifiacation
    return Upload.LIST_IGNORE;
  }
  fileList.value = file;
  // ↓ 获取所需要上传图片的 Base64 编码
  getBase64(fileList.value, (cb_img: string) => {
    // 将获取到的所要上传图片的 Base64 编码渲染到图片上
    base64img.value = cb_img;
  })
  return false;
}

/**
 * 点击上传按钮的回调
 */
function triggerUpload() {
  const formData = new FormData();

  // 对文件列表 判空
  if (fileList.value != null) {
    formData.append("file", fileList.value as any);
  } else {
    Notice.error("文件不能为空!")
    return Upload.LIST_IGNORE;
  }

  // ↓ 在上传过程中,按钮为 loading 状态
  btnLoading.value = true;

  // 请求上传接口
  fruitApi({
    method: 'put',
    url: 'api/upload',
    data: formData
  })
      .then((resp: any) => {
        console.log(resp);
        if (resp.code === 1) {
          Notice.success(<string>resp.data);
          changeUploadItemColor("#49aa19");
        } else {
          Notice.error("上传失败~");
          changeUploadItemColor("#ff4d4f");
          // ↑ 下面会提到这个函数
        }
        btnLoading.value = false;
      })
      .catch((err) => {
        console.log(err);
        Notice.error("发生了错误~");
        btnLoading.value = false;
        changeUploadItemColor("#ff4d4f");
      })
}

/**
 * 待上传图片被删除的回调
 */
function handleRemove() {
  fileList.value = null;
  // ↑ 置空待上传文件列表
  base64img.value = null;
  // ↑ 显示默认占位图
}


/**
 * 上传图片成功或失败后 list 变色的函数
 */
type uploadItemColor = "#49aa19" | "#ff4d4f";
// ↑ 两个颜色 绿 和 红
function changeUploadItemColor(color: uploadItemColor) {
  const uploadListItem = document.querySelector(".ant-upload-list-item-name");
  // ↑ 类名是 antdv 规定的,选择这个类名即可
  (uploadListItem as any).style.color = color;
  // ↑ 使item文字变色
}

这次真的是把 TypeScript 写成了 anyScript,中间不知道用了多少的类型断言和 :any 😟

End

开头已经展示过页面效果啦,就不再测试了 😄

posted @ 2022-10-07 16:45  HuStoking  阅读(1363)  评论(0编辑  收藏  举报